Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
_become | 884968 | 10 days ago | IN | 0 S | 0.00005867 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TradingFloorV1
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/ITradingFloorV1.sol"; import "../interfaces/IRegistryV1.sol"; import "../interfaces/ILexPoolV1.sol"; import "../interfaces/IPoolAccountantV1.sol"; import "./TradingFloorStorage.sol"; import "./TradingFloorProxy.sol"; /** * @title TradingFloorV1 * @dev The TradingFloor contract is the main contract for the Lynx trading platform. * It handles the opening, updating and closing of positions. */ contract TradingFloorV1 is TradingFloorV1Storage, ITradingFloorV1Functionality, LexErrors { using SafeERC20 for IERC20; // ***** Constants ***** uint public constant MAX_FEE_FRACTION_FOR_CANCEL = FRACTION_SCALE / 100; // FRACTION_SCALE // ***** Events ***** event SettlementAssetAdded( address indexed asset, address indexed lexPool, address indexed poolAccountant ); event NumberUpdated(string indexed name, uint value); event PairPausedChange(uint indexed pairId, bool indexed isPaused); event PositionIdentifiersStored( bytes32 indexed positionId, PositionIdentifiers identifiers ); event PendingPositionStored( bytes32 indexed positionId, PositionPhase phase, PositionRequestIdentifiers requestIdentifiers, PositionRequestParams requestParams, uint32 _spreadReductionF ); event PositionOpenCancelledByMarketPriceRange( bytes32 indexed positionId, uint64 triggerPrice ); event PositionOpenCancelledByCap( bytes32 indexed positionId, CapType capType, uint256 value ); event PositionOpened( bytes32 indexed positionId, uint64 openPrice, uint64 tp, uint64 sl, uint totalOpenFee, uint lexFeePart ); event PositionSetForMarketClose( bytes32 indexed positionId, uint64 _minPrice, uint64 _maxPrice ); event PositionClosedMarket( bytes32 indexed positionId, uint triggerPrice, uint tradeValue, int profitPrecision ); event PositionClosedLimit( bytes32 indexed positionId, LimitTrigger indexed limitTrigger, uint triggerPrice, uint effectiveClosePrice, uint tradeValue, int profitPrecision ); event FeeRegistered( bytes32 indexed positionId, address indexed token, FeeType indexed feeType, uint amount ); event FeeCollected( address indexed token, FeeType indexed feeType, address indexed receiver, uint amount ); event PendingPositionCancelled( bytes32 indexed positionId, address indexed source, uint fee ); event PositionMarketCloseCancelled( bytes32 indexed positionId, address indexed source, uint fee ); event PendingPositionUpdated( bytes32 indexed positionId, uint64 tp, uint64 sl, uint64 minPrice, uint64 maxPrice ); event OpenedPositionUpdated( bytes32 indexed positionId, uint16 indexed pairId, bool buy, PositionField indexed updatedField, uint64 fieldValue ); // ***** Modifiers ***** modifier onlyTradersPortal() { require( IRegistryV1(registry).isTradersPortalAndLocker(msg.sender), "!TradersPortal" ); _; } modifier onlyTriggers() { require(IRegistryV1(registry).isTriggersAndLocker(msg.sender), "!Triggers"); _; } modifier onlyTradersPortalOrTriggers() { require( IRegistryV1(registry).isTradersPortalOrTriggersAndLocker(msg.sender), "!(TradersPortal||Triggers)" ); _; } // ***** Views ***** /** * Generates the hash used to identify a position */ function generatePositionHashId( address settlementAsset, address trader, uint16 pairId, uint32 index ) public pure returns (bytes32 hashId) { hashId = keccak256( abi.encodePacked(settlementAsset, trader, pairId, index) ); } /** * Builds the structs with info needed fo 'Triggers' interactions */ function getPositionTriggerInfo( bytes32 _positionId ) external view returns ( PositionPhase positionPhase, uint64 timestamp, uint16 pairId, bool long, uint32 spreadReductionF ) { return ( positionsById[_positionId].phase, positionsById[_positionId].inPhaseSince, positionIdentifiersById[_positionId].pairId, positionsById[_positionId].long, positionsById[_positionId].spreadReductionF ); } /** * Builds the structs with info needed for 'TradersPortal' interactions */ function getPositionPortalInfo( bytes32 _positionId ) external view returns (PositionPhase positionPhase, uint64 timestamp, address trader) { return ( positionsById[_positionId].phase, positionsById[_positionId].inPhaseSince, positionIdentifiersById[_positionId].trader ); } /** * Builds the structs with info needed for 'PoolAccountnat' interactions */ function getPositionRegistrationParams( bytes32 _positionId ) public view returns ( PoolAccountantStructs.PositionRegistrationParams memory registrationParams ) { Position memory position = positionsById[_positionId]; registrationParams.collateral = position.collateral; registrationParams.leverage = position.leverage; registrationParams.openPrice = position.openPrice; registrationParams.long = position.long; registrationParams.tp = positionLimitsInfoById[_positionId].tp; return registrationParams; } /** * @return true if the given asset has a Lex defined for it */ function isSettlementAssetSupported( address settlementAsset ) public view returns (bool) { return lexPoolForAsset[settlementAsset] != address(0); } /** * @return An array of all addresses with an active/pending position in the given SA+pair combination */ function pairTradersArray( address _asset, uint _pairIndex ) external view returns (address[] memory) { return pairTraders[_asset][_pairIndex]; } // ***** Initialization functions ***** /** * @notice Part of the Proxy mechanism */ function _become(TradingFloorProxy tradingFloorProxy) public { require(msg.sender == tradingFloorProxy.admin(), "!proxy.admin"); require(tradingFloorProxy._acceptImplementation() == 0, "fail"); } // ***** Registry Functions ***** /** * Adds a new settlement asset to the trading floor with the given LexPool and PoolAccountant * @dev This function is only callable by the registry */ function supportNewSettlementAsset( address _asset, address _lexPool, address _poolAccountant ) external { require(msg.sender == registry, "!Registry"); require(lexPoolForAsset[_asset] == address(0), "ASSET_ALREADY_SUPPORTED"); // Store addresses lexPoolForAsset[_asset] = _lexPool; poolAccountantForAsset[_asset] = _poolAccountant; emit SettlementAssetAdded(_asset, _lexPool, _poolAccountant); } // ***** Admin Functions ***** /** * Setter for numeric parameters */ function setTradeParam( AdminNumericParam numericParam, uint value ) external onlyAdmin { require(value > 0, "CANNOT_BE_ZERO"); string memory name; if (numericParam == AdminNumericParam.MAX_TRADES_PER_PAIR) { name = "maxTradesPerPair"; maxTradesPerPair = value; } else if (numericParam == AdminNumericParam.MAX_SL_F) { // Note: Forcing a value of 50% or above require(value >= (FRACTION_SCALE * 50) / 100, "TRADE_PARAM_RESTRICTION"); name = "maxSlF"; maxSlF = value; } else if (numericParam == AdminNumericParam.MAX_SANITY_PROFIT_F) { // Note : Forcing a value of 200% or above require(value >= 2 * FRACTION_SCALE, "TRADE_PARAM_RESTRICTION"); name = "maxSanityProfitF"; maxSanityProfitF = value; } else { revert("UNSUPPORTED"); } emit NumberUpdated(name, value); } /** * Allows to pause/unpause the opening/updating of positions in the given pair */ function setPairPaused(uint _pairId, bool _isPaused) external onlyAdmin { pausedPairs[_pairId] = _isPaused; emit PairPausedChange(_pairId, _isPaused); } // ***** Traders Portal Interaction ***** /** * This function stores the request for opening a new Position * @return positionId The id of the new position (pending to be opened) */ function storePendingPosition( OpenOrderType _orderType, PositionRequestIdentifiers memory _requestIdentifiers, PositionRequestParams memory _requestParams, uint32 _spreadReductionF ) external override onlyTradersPortal returns (bytes32 positionId) { require( isSettlementAssetSupported(_requestIdentifiers.settlementAsset), "NON_SUPPORTED_SETTLEMENT_ASSET" ); require(!pausedPairs[_requestIdentifiers.pairId], "PAIR_PAUSED"); require( _orderType == OpenOrderType.MARKET || _orderType == OpenOrderType.LIMIT, "UNSUPPORTED_ORDER_TYPE" ); requireValidOpenTradeParameters( _requestParams.long, _requestParams.minPrice, _requestParams.maxPrice, _requestParams.tp, _requestParams.sl ); require( pairTradersInfo[_requestIdentifiers.settlementAsset][ _requestIdentifiers.trader ][_requestIdentifiers.pairId].positionsCounter < maxTradesPerPair, "MAX_TRADES_PER_PAIR" ); require( _requestIdentifiers.positionIndex <= maxTradesPerPair && _requestIdentifiers.positionIndex != 0, "INVALID_INDEX" ); positionId = storeIdentifiersIfNeeded( _requestIdentifiers.settlementAsset, _requestIdentifiers.trader, _requestIdentifiers.pairId, _requestIdentifiers.positionIndex ); takeSettlement( _requestIdentifiers.settlementAsset, _requestIdentifiers.trader, _requestParams.collateral ); // Add/Increase in pair traders increaseOrAddToPairTradersLists( _requestIdentifiers.settlementAsset, _requestIdentifiers.trader, _requestIdentifiers.pairId ); Position storage position = positionsById[positionId]; require(position.collateral == 0, "ID_USED"); position.spreadReductionF = _spreadReductionF; position.long = _requestParams.long; position.leverage = _requestParams.leverage; position.collateral = _requestParams.collateral; PositionPhase phase = _orderType == OpenOrderType.MARKET ? PositionPhase.OPEN_MARKET : PositionPhase.OPEN_LIMIT; position.phase = phase; position.inPhaseSince = uint64(block.timestamp); PositionLimitsInfo storage positionLimitInfo = positionLimitsInfoById[ positionId ]; positionLimitInfo.tp = _requestParams.tp; positionLimitInfo.sl = _requestParams.sl; PositionTriggerPrices storage triggerPrices = triggerPricesById[positionId]; triggerPrices.minPrice = _requestParams.minPrice; triggerPrices.maxPrice = _requestParams.maxPrice; triggerPrices.tpByFraction = _requestParams.tpByFraction; triggerPrices.slByFraction = _requestParams.slByFraction; emit PendingPositionStored( positionId, phase, _requestIdentifiers, _requestParams, _spreadReductionF ); } /** * Sets the given position to be market closed */ function setOpenedPositionToMarketClose( bytes32 _positionId, uint64 _minPrice, uint64 _maxPrice ) external override onlyTradersPortal { // note : using 'storage' to reduce gas cost and contract size Position storage position = positionsById[_positionId]; require(position.collateral > 0, "NO_SUCH_POSITION"); require(position.phase == PositionPhase.OPENED, "WRONG_PHASE"); position.phase = PositionPhase.CLOSE_MARKET; position.inPhaseSince = uint64(block.timestamp); PositionTriggerPrices storage triggerPrices = triggerPricesById[ _positionId ]; triggerPrices.minPrice = _minPrice; triggerPrices.maxPrice = _maxPrice; emit PositionSetForMarketClose(_positionId, _minPrice, _maxPrice); } /** * Updates one of the fields in a pending LIMIT_OPEN position */ function updatePendingPosition_openLimit( bytes32 _positionId, uint64 _minPrice, uint64 _maxPrice, uint64 _tp, uint64 _sl ) external override onlyTradersPortal { Position storage _position = positionsById[_positionId]; require(_position.phase == PositionPhase.OPEN_LIMIT, "WRONG_PHASE"); require( !pausedPairs[positionIdentifiersById[_positionId].pairId], "PAIR_PAUSED" ); requireValidOpenTradeParameters( _position.long, _minPrice, _maxPrice, _tp, _sl ); // Update the pending position timestamp _position.inPhaseSince = uint64(block.timestamp); // Update the position locally PositionLimitsInfo storage _positionLimitInfo = positionLimitsInfoById[ _positionId ]; _positionLimitInfo.tp = _tp; _positionLimitInfo.sl = _sl; // Note : Not updating the timestamps as they only need to be updated for Opened positions PositionTriggerPrices storage triggerPrices = triggerPricesById[ _positionId ]; triggerPrices.minPrice = _minPrice; triggerPrices.maxPrice = _maxPrice; emit PendingPositionUpdated(_positionId, _tp, _sl, _minPrice, _maxPrice); } // ***** Triggers Interaction ***** /** * Called by the triggers in order to Open a new position by market price */ function openNewPosition_market( bytes32 _positionId, uint64 assetEffectivePrice, uint256 feeForCancellation ) external onlyTriggers { openNewTradeInternal( _positionId, PositionPhase.OPEN_MARKET, assetEffectivePrice, feeForCancellation ); } /** * Called by the triggers in order to Open a new position by reached limit */ function openNewPosition_limit( bytes32 _positionId, uint64 assetEffectivePrice, uint256 feeForCancellation ) external onlyTriggers { openNewTradeInternal( _positionId, PositionPhase.OPEN_LIMIT, assetEffectivePrice, feeForCancellation ); } /** * Called by the triggers in order to Close an existing position by market price */ function closeExistingPosition_Market( bytes32 _positionId, uint64, // assetPrice uint64 effectivePrice ) external override onlyTriggers { PositionTriggerPrices memory triggerPrices = triggerPricesById[_positionId]; require(triggerPrices.maxPrice > 0, "NO_SUCH_POSITION"); if ( triggerPrices.minPrice > effectivePrice || triggerPrices.maxPrice < effectivePrice ) { cancelMarketCloseForPositionInternal( address(this), _positionId, CloseOrderType.MARKET ); } else { ( uint tradeValue, int profitPrecision, uint finalClosingPrice ) = closeExistingTradeInternal( _positionId, effectivePrice, PositionCloseType.MARKET ); emit PositionClosedMarket( _positionId, finalClosingPrice, tradeValue, profitPrecision ); } } /** * Called by the triggers in order to Close an existing position by a reached limit value */ function closeExistingPosition_Limit( bytes32 _positionId, LimitTrigger limitTrigger, uint64, // assetPrice uint64 effectivePrice ) external override onlyTriggers { Position memory position = positionsById[_positionId]; require(position.collateral > 0, "NO_SUCH_POSITION"); PositionLimitsInfo memory positionLimitInfo = positionLimitsInfoById[ _positionId ]; bool triggerValid = false; uint effectiveClosingPrice; PositionCloseType positionCloseType; if (limitTrigger == LimitTrigger.SL) { triggerValid = position.long ? effectivePrice <= positionLimitInfo.sl : effectivePrice >= positionLimitInfo.sl; effectiveClosingPrice = positionLimitInfo.sl; positionCloseType = PositionCloseType.SL; } else if (limitTrigger == LimitTrigger.TP) { triggerValid = position.long ? effectivePrice >= positionLimitInfo.tp : effectivePrice <= positionLimitInfo.tp; effectiveClosingPrice = positionLimitInfo.tp; positionCloseType = PositionCloseType.TP; } else if (limitTrigger == LimitTrigger.LIQ) { // Note : The Accountant will be the one to adjust the price for liquidation triggerValid = true; effectiveClosingPrice = effectivePrice; positionCloseType = PositionCloseType.LIQ; } else { revert("WRONG_LIMIT_TRIGGER"); } // Revert if the conditions are not met for triggering require(triggerValid, "FALSE_TRIGGER"); ( uint tradeValue, int profitPrecision, uint finalClosingPrice ) = closeExistingTradeInternal( _positionId, effectiveClosingPrice, positionCloseType ); // Checking again for liq to allow quicker failure in TP and SL if (positionCloseType == PositionCloseType.LIQ) { triggerValid = position.long ? effectivePrice <= finalClosingPrice : effectivePrice >= finalClosingPrice; require(triggerValid, "FALSE_TRIGGER"); } emit PositionClosedLimit( _positionId, limitTrigger, effectivePrice, finalClosingPrice, tradeValue, profitPrecision ); } /** * Updates a PositionField of an OPEN position */ function updateOpenedPosition( bytes32 positionId, PositionField updateField, uint64 fieldValue, uint64 effectivePrice ) external onlyTriggers { Position storage p = positionsById[positionId]; PositionLimitsInfo storage limitInfo = positionLimitsInfoById[positionId]; PositionIdentifiers memory identifiers = positionIdentifiersById[ positionId ]; require(p.collateral > 0, "NO_SUCH_POSITION"); require(p.phase == PositionPhase.OPENED, "WRONG_PHASE"); IPoolAccountantV1 poolAccountant = IPoolAccountantV1( poolAccountantForAsset[identifiers.settlementAsset] ); uint64 tpToUse; uint64 slToUse; if (updateField == PositionField.TP) { uint64 correctedTp = correctTp( uint64(poolAccountant.maxGainF()), p.openPrice, p.leverage, fieldValue, p.long ); // Sanity require(correctedTp == fieldValue, "BAD_FIELD_VALUE"); require(correctedTp != limitInfo.tp, "SAME_TP"); tpToUse = correctedTp; slToUse = limitInfo.sl; limitInfo.tpLastUpdated = uint64(block.timestamp); // Register the change in the LexPool // Might revert if a cap is reached poolAccountant.registerUpdateTp( positionId, identifiers.trader, identifiers.pairId, p.collateral, p.leverage, p.long, p.openPrice, limitInfo.tp, tpToUse ); } else if (updateField == PositionField.SL) { uint64 correctedSl = correctSl( uint64(poolAccountant.maxGainF()), p.openPrice, p.leverage, fieldValue, p.long ); // Sanity require(correctedSl == fieldValue, "BAD_FIELD_VALUE"); require(correctedSl != limitInfo.sl, "SAME_SL"); tpToUse = limitInfo.tp; slToUse = correctedSl; limitInfo.slLastUpdated = uint64(block.timestamp); } else { revert("UNSUPPORTED"); } uint effectiveMinPrice = p.openPrice > effectivePrice ? effectivePrice : p.openPrice; uint effectiveMaxPrice = p.openPrice < effectivePrice ? effectivePrice : p.openPrice; // Ensure the new params are valid requireValidOpenTradeParameters( p.long, effectiveMinPrice, effectiveMaxPrice, tpToUse, slToUse ); limitInfo.sl = slToUse; limitInfo.tp = tpToUse; emit OpenedPositionUpdated( positionId, identifiers.pairId, p.long, updateField, fieldValue ); } // ***** Traders Portal/Triggers Shared Interaction ***** /** * Cancel a pending open position, returning assets to trader. */ function cancelPendingPosition( bytes32 _positionId, OpenOrderType _orderType, uint feeFraction ) external override onlyTradersPortalOrTriggers { require(feeFraction <= MAX_FEE_FRACTION_FOR_CANCEL, "FEE_FRACTION_TOO_BIG"); // PendingOpenTradeOrder memory _order = OrderBookInterfaceV1(orderBook).readAndDeleteOpenOrder(_positionId, _orderType); Position memory position = positionsById[_positionId]; require(positionsById[_positionId].collateral > 0, "NO_SUCH_POSITION"); PositionIdentifiers memory identifiers = positionIdentifiersById[ _positionId ]; if (_orderType == OpenOrderType.MARKET) { require(position.phase == PositionPhase.OPEN_MARKET, "NOT_MARKET_ORDER"); } else if (_orderType == OpenOrderType.LIMIT) { require(position.phase == PositionPhase.OPEN_LIMIT, "NOT_LIMIT_ORDER"); } else { revert("WRONG_ORDER_TYPE"); } settleCanceledOpenOrderInternal( _positionId, identifiers.settlementAsset, identifiers.trader, identifiers.pairId, position.collateral, position.leverage, feeFraction, msg.sender ); } /** * Cancel a CLOSE_MARKET position, returning the position to an OPEN phase. * @dev Currently no fee is being taken for this action */ function cancelMarketCloseForPosition( bytes32 _positionId, CloseOrderType _orderType, uint // feeFraction ) external override onlyTradersPortalOrTriggers { cancelMarketCloseForPositionInternal(msg.sender, _positionId, _orderType); } /** * Handles the cancellation of a "market close" order */ function cancelMarketCloseForPositionInternal( address source, bytes32 _positionId, CloseOrderType _orderType ) internal { require(positionsById[_positionId].collateral > 0, "NO_SUCH_POSITION"); delete triggerPricesById[_positionId]; if (_orderType == CloseOrderType.MARKET) { require( positionsById[_positionId].phase == PositionPhase.CLOSE_MARKET, "WRONG_PHASE" ); } else { revert("WRONG_ORDER_TYPE"); } positionsById[_positionId].phase = PositionPhase.OPENED; positionsById[_positionId].inPhaseSince = uint64(block.timestamp); emit PositionMarketCloseCancelled(_positionId, source, 0); } // ***** Fees Manager Interaction ***** /** * Sends all fee accrued in the SA+feeType to the '_to' address * @dev Allows a dynamic and flexible way to direct fees. */ function collectFee(address _asset, FeeType _feeType, address _to) external { require( msg.sender == IRegistryV1(registry).feesManagers(_asset), "!FeesManager" ); collectFeeInternal(_asset, _feeType, _to); } // ***** Internal Position Open/Close logic ***** /** * Stores the identifying values of the position. * @dev Saves gas after the first time a SA-trader-pair-index position was registered in this contract * @return positionId The position id that matched these identifiers */ function storeIdentifiersIfNeeded( address settlementAsset, address trader, uint16 pairId, uint32 index ) internal returns (bytes32 positionId) { positionId = generatePositionHashId(settlementAsset, trader, pairId, index); PositionIdentifiers storage identifiers = positionIdentifiersById[ positionId ]; // Store the identifier once if (identifiers.index == 0) { identifiers.settlementAsset = settlementAsset; identifiers.trader = trader; identifiers.pairId = pairId; identifiers.index = index; emit PositionIdentifiersStored(positionId, identifiers); } } /** * Handles verifications and logic for the opening of a new position. * @dev This function will "swallow" the "CapError" custom error that can be thrown by the 'PoolAccountant' contract * and in such case will proceed to cancel the open order. */ function openNewTradeInternal( bytes32 _positionId, PositionPhase _expectedPhase, uint64 assetEffectivePrice, uint256 feeForCancellation ) internal { PositionTriggerPrices memory triggerPrices = triggerPricesById[_positionId]; Position memory _position = positionsById[_positionId]; require(_position.collateral > 0, "NO_SUCH_POSITION"); PositionIdentifiers memory identifiers = positionIdentifiersById[ _positionId ]; require(!pausedPairs[identifiers.pairId], "PAIR_PAUSED"); require(_position.phase == _expectedPhase, "WRONG_PHASE"); if (_expectedPhase == PositionPhase.OPEN_MARKET) { if ( triggerPrices.minPrice > assetEffectivePrice || triggerPrices.maxPrice < assetEffectivePrice ) { emit PositionOpenCancelledByMarketPriceRange( _positionId, assetEffectivePrice ); settleCanceledOpenOrderInternal( _positionId, identifiers.settlementAsset, identifiers.trader, identifiers.pairId, _position.collateral, _position.leverage, feeForCancellation, address(this) ); return; } } else if (_expectedPhase == PositionPhase.OPEN_LIMIT) { // Limit Orders cannot be triggered if the price is wrong require( triggerPrices.minPrice <= assetEffectivePrice && triggerPrices.maxPrice >= assetEffectivePrice, "PRICE_RANGE" ); } else { revert("UNSUPPORTED"); } address poolAccountant = poolAccountantForAsset[ identifiers.settlementAsset ]; PositionLimitsInfo memory positionLimits = storeCorrectLimitsForOpenedPosition( _positionId, poolAccountant, _position.leverage, _position.long, assetEffectivePrice, triggerPrices ); try IPoolAccountantFunctionality(poolAccountant).registerOpenTrade( _positionId, identifiers.trader, identifiers.pairId, _position.collateral, _position.leverage, _position.long, positionLimits.tp, assetEffectivePrice ) returns (uint openFeePart, uint lexFeePart) { Position storage _positionStorage = positionsById[_positionId]; _positionStorage.openPrice = assetEffectivePrice; // Store the position's initial collateral initialCollateralByPositionId[_positionId] = _position.collateral; // Note : Subtracting the open fee before storing the position _positionStorage.collateral = _position.collateral - openFeePart; // Mark the position as opened _positionStorage.phase = PositionPhase.OPENED; _positionStorage.inPhaseSince = uint64(block.timestamp); registerFeeInternal( _positionId, identifiers.settlementAsset, FeeType.OPEN_FEE, openFeePart - lexFeePart ); sendSettlement( identifiers.settlementAsset, lexPoolForAsset[identifiers.settlementAsset], lexFeePart ); delete triggerPricesById[_positionId]; emit PositionOpened( _positionId, assetEffectivePrice, positionLimits.tp, positionLimits.sl, openFeePart, lexFeePart ); } catch Error(string memory error) { revert(error); } catch (bytes memory err) { if (bytes4(err) == LexErrors.CapError.selector) { LexErrors.CapType capType; uint256 value; assembly { capType := mload(add(err, 0x24)) value := mload(add(err, 0x44)) } emit PositionOpenCancelledByCap(_positionId, capType, value); settleCanceledOpenOrderInternal( _positionId, identifiers.settlementAsset, identifiers.trader, identifiers.pairId, _position.collateral, _position.leverage, feeForCancellation, address(this) ); } else { revert(); } } } /** * Stores the limits values of a newly opened position (after correcting them to the valid ranges if needed) */ function storeCorrectLimitsForOpenedPosition( bytes32 positionId, address poolAccountant, uint32 leverage, bool isLong, uint64 assetEffectivePrice, PositionTriggerPrices memory triggerPrices ) internal returns (PositionLimitsInfo memory positionLimits) { uint maxGainF = IPoolAccountantV1(poolAccountant).maxGainF(); positionLimits = positionLimitsInfoById[positionId]; require( positionLimits.tp == 0 || triggerPrices.tpByFraction == 0, "MULTIPLE_TP_DEFINITIONS" ); require( positionLimits.sl == 0 || triggerPrices.slByFraction == 0, "MULTIPLE_SL_DEFINITIONS" ); if (triggerPrices.tpByFraction > 0) { uint64 priceDiff = calculatePriceDiffFromFractionAndLeverage( assetEffectivePrice, triggerPrices.tpByFraction, leverage ); positionLimits.tp = isLong ? assetEffectivePrice + priceDiff : priceDiff < assetEffectivePrice ? assetEffectivePrice - priceDiff : 0; } if (triggerPrices.slByFraction > 0) { uint64 priceDiff = calculatePriceDiffFromFractionAndLeverage( assetEffectivePrice, triggerPrices.slByFraction, leverage ); positionLimits.sl = isLong ? priceDiff < assetEffectivePrice ? assetEffectivePrice - priceDiff : 0 : assetEffectivePrice + priceDiff; } positionLimits.tp = correctTp( uint64(maxGainF), assetEffectivePrice, leverage, positionLimits.tp, isLong ); positionLimits.tpLastUpdated = uint64(block.timestamp); positionLimits.sl = correctSl( uint64(maxGainF), assetEffectivePrice, leverage, positionLimits.sl, isLong ); positionLimits.slLastUpdated = uint64(block.timestamp); // Store positionLimitsInfoById[positionId] = positionLimits; } /** * Handles the all closing types of an existing opened position. */ function closeExistingTradeInternal( bytes32 _positionId, uint effectivePrice, PositionCloseType positionCloseType ) internal returns (uint tradeValue, int profitPrecision, uint finalClosingPrice) { PositionIdentifiers memory identifiers = positionIdentifiersById[ _positionId ]; PoolAccountantStructs.PositionRegistrationParams memory positionRegistrationParams = getPositionRegistrationParams( _positionId ); require(positionRegistrationParams.collateral > 0, "NO_SUCH_POSITION"); // Note : 'tradeValue' is the value after subtracting the 'closeFeePart' ( uint closeFeePart, uint _tradeValue, int _profitPrecision, uint _finalClosePrice ) = registerTradeCloseInLexInternal( _positionId, identifiers, positionRegistrationParams, effectivePrice, positionCloseType ); if (_tradeValue > positionRegistrationParams.collateral) { uint totalProfitF = ((_tradeValue - positionRegistrationParams.collateral) * FRACTION_SCALE) / positionRegistrationParams.collateral; require(totalProfitF <= maxSanityProfitF, "INVALID_PROFIT"); } profitPrecision = _profitPrecision; tradeValue = _tradeValue; finalClosingPrice = _finalClosePrice; // sanity require( closeFeePart <= positionRegistrationParams.collateral, "CLOSE_FEE_LARGER_THAN_POSITION" ); registerFeeInternal( _positionId, identifiers.settlementAsset, FeeType.CLOSE_FEE, closeFeePart ); // Decrease/Remove from the pair traders decreaseOrRemoveFromPairTradersLists( identifiers.settlementAsset, identifiers.trader, identifiers.pairId ); // Delete the position delete positionsById[_positionId]; delete positionLimitsInfoById[_positionId]; delete initialCollateralByPositionId[_positionId]; // Settle the position settleTradeCloseInternal( identifiers.trader, identifiers.settlementAsset, tradeValue, positionRegistrationParams.collateral, closeFeePart ); } // **** LeX-Center Interaction **** /** * Utility function to inform the "PoolAccountant" that a position is being closed and retrieve it's closing values. * @dev Using a separate function to bypass the "stack too depp" issue. */ function registerTradeCloseInLexInternal( bytes32 _positionId, PositionIdentifiers memory _identifiers, PoolAccountantStructs.PositionRegistrationParams memory positionRegistrationParams, uint closePrice, PositionCloseType positionCloseType ) internal returns ( uint closeFeePart, uint tradeValue, int profitPrecision, uint finalClosePrice ) { return IPoolAccountantFunctionality( poolAccountantForAsset[_identifiers.settlementAsset] ).registerCloseTrade( _positionId, _identifiers.trader, _identifiers.pairId, positionRegistrationParams, closePrice, positionCloseType ); } // **** Trade Closing Settlement **** /** * Handles the logic for cancellation of a position in any "pending open" for any reason (trader request/timeout/cap error etc...) */ function settleCanceledOpenOrderInternal( bytes32 positionId, address settlementAsset, address trader, uint16 pairId, uint collateral, uint32 leverage, uint feeF, address canceller ) internal { delete positionsById[positionId]; delete triggerPricesById[positionId]; uint cancellationFee = calculateFractionInternal( calculateLeveragedPosition(collateral, leverage), feeF ); registerFeeInternal( positionId, settlementAsset, FeeType.TRIGGER_FEE, cancellationFee ); // Decrease/Remove from the pair traders decreaseOrRemoveFromPairTradersLists(settlementAsset, trader, pairId); uint collateralLeft = collateral - cancellationFee; sendSettlement(settlementAsset, trader, collateralLeft); emit PendingPositionCancelled(positionId, canceller, cancellationFee); } /** * Handles the asset transferring of a closing position. */ function settleTradeCloseInternal( address trader, address settlementAsset, uint tradeValue, uint tradeCollateral, uint closingFee ) internal { ILexPoolV1 lexToken = ILexPoolV1(lexPoolForAsset[settlementAsset]); uint assetForTraderFromFloor; // Trade gain if (tradeValue >= tradeCollateral) { // Note : The closing fee stays in the TradingFloor assetForTraderFromFloor = tradeCollateral - closingFee; uint assetForTraderFromPool = tradeValue - assetForTraderFromFloor; lexToken.sendAssetToTrader(trader, assetForTraderFromPool); } // Trade loss else { assetForTraderFromFloor = tradeValue; uint diff = tradeCollateral - tradeValue; if (diff > closingFee) { // Send to the lex sendSettlement(settlementAsset, address(lexToken), diff - closingFee); } else { // Take the missing amount for the 'closingFee' from the lex lexToken.sendAssetToTrader(address(this), closingFee - diff); } } sendSettlement(settlementAsset, trader, assetForTraderFromFloor); } // ***** Internal Fees ***** /** * Sends all fees collected in for the SA+FeeType and zeros the counter */ function collectFeeInternal( address _asset, FeeType _feeType, address _to ) internal { uint amount = feesMap[_asset][_feeType]; feesMap[_asset][_feeType] = 0; IERC20(_asset).safeTransfer(_to, amount); emit FeeCollected(_asset, _feeType, _to, amount); } /** * Adds '_amount' to the SA+FeeType counter */ function registerFeeInternal( bytes32 _positionId, address _token, FeeType _feeType, uint _amount ) internal { if (_amount > 0) { feesMap[_token][_feeType] += _amount; emit FeeRegistered(_positionId, _token, _feeType, _amount); } } // ***** Internal Tokens Utils ***** /** * Utility function to safely take an ERC20 settlement asset from a pre-approved account */ function takeSettlement( address settlementAsset, address from, uint amount ) internal { if (amount > 0) { uint balanceBefore = IERC20(settlementAsset).balanceOf(address(this)); IERC20(settlementAsset).safeTransferFrom(from, address(this), amount); uint balanceAfter = IERC20(settlementAsset).balanceOf(address(this)); require(balanceAfter - balanceBefore == amount, "DID_NOT_RECEIVE_EXACT"); } } /** * Utility function to safely send an ERC20 settlement asset to an account */ function sendSettlement( address settlementAsset, address to, uint amount ) internal { if (amount > 0) { IERC20(settlementAsset).safeTransfer(to, amount); } } // ***** Internal State Utils ***** /** * Handles counter increment for positionsCounter and addition to the 'pairTraders' list in case this is the * trader's first position in this SA+pair */ function increaseOrAddToPairTradersLists( address settlementAsset, address trader, uint16 pairId ) internal { pairTradersInfo[settlementAsset][trader][pairId].positionsCounter++; if ( pairTradersInfo[settlementAsset][trader][pairId].positionsCounter == 1 ) { pairTraders[settlementAsset][pairId].push(trader); pairTradersInfo[settlementAsset][trader][pairId].positionInArray = uint32( pairTraders[settlementAsset][pairId].length ); } } /** * Handles counter reduction for positionsCounter and complete removal from the 'pairTraders' list in case the * trader has no more positions in this SA+pair */ function decreaseOrRemoveFromPairTradersLists( address settlementAsset, address trader, uint16 pairId ) internal { if ( pairTradersInfo[settlementAsset][trader][pairId].positionsCounter == 1 ) { address[] storage p = pairTraders[settlementAsset][pairId]; if (p.length > 1) { uint32 _pairTradersPosition = pairTradersInfo[settlementAsset][trader][ pairId ].positionInArray; p[_pairTradersPosition - 1] = p[p.length - 1]; pairTradersInfo[settlementAsset][p[_pairTradersPosition - 1]][pairId] .positionInArray = _pairTradersPosition; } delete pairTradersInfo[settlementAsset][trader][pairId]; p.pop(); } else { pairTradersInfo[settlementAsset][trader][pairId].positionsCounter--; } } // ***** Internal Calculation Utils ***** /** * Utility function to calculate a 'FRACTION_SCALE' value of a given amount * @return The fraction value out of the given amount */ function calculateFractionInternal( uint amount, uint feeFraction ) internal pure returns (uint) { return (amount * feeFraction) / FRACTION_SCALE; } // Trade validity functions /** * Runs some sanity requires to ensure the position values are in the right range */ function requireValidOpenTradeParameters( bool isLong, uint minPrice, uint maxPrice, uint tp, uint sl ) internal pure { require(minPrice <= maxPrice, "MIN_MAX_REVERSE"); require(tp == 0 || (isLong ? tp > maxPrice : tp < minPrice), "WRONG_TP"); require(sl == 0 || (isLong ? sl < minPrice : sl > maxPrice), "WRONG_SL"); } /** * Receives the wanted sl for a position (with other relevant params) and makes sure the value is within the expected range * @notice In case of TP == 0 or a breach of max value, the value returned will be the max allowed value * (can be capped by 0 in case of a SHORT position) */ function correctTp( uint64 maxGainF, uint64 openPrice, uint64 leverage, // scaled up from 32 uint64 tp, bool buy ) internal pure returns (uint64) { if ( tp == 0 || currentProfitFraction(maxGainF, openPrice, tp, buy, leverage) >= int64(maxGainF) ) { uint64 tpDiff = uint64( ((uint256(openPrice) * uint256(maxGainF)) * LEVERAGE_SCALE) / uint256(leverage) / FRACTION_SCALE ); return buy ? openPrice + tpDiff : tpDiff <= openPrice ? openPrice - tpDiff : 0; } return tp; } /** * Receives the wanted sl for a position (with other relevant params) and makes sure the value is within the expected range * @notice In case of SL == 0 or a breach of max value, the value returned will be the max allowed value * (can be capped by 0 in case of a LONG position) */ function correctSl( uint64 maxGainF, uint64 openPrice, uint64 leverage, // scaled up from 32 uint64 sl, bool buy ) internal view returns (uint64) { if ( sl == 0 || currentProfitFraction(maxGainF, openPrice, sl, buy, leverage) <= int(maxSlF) * -1 ) { uint64 slDiff = uint64( (uint256(openPrice) * maxSlF * LEVERAGE_SCALE) / uint256(leverage) / FRACTION_SCALE ); return buy ? slDiff <= openPrice ? openPrice - slDiff : 0 : openPrice + slDiff; } return sl; } /** * Calculates the (positive or negative) profit fraction by given position values * @return f The profit fraction, with scale of FRACTION_SCALE */ function currentProfitFraction( uint64 maxGainF, uint64 openPrice, uint64 currentPrice, bool buy, uint64 leverage // scaled from 32 ) internal pure returns (int64 f) { int64 maxPnlF = int64(maxGainF); int64 priceDiff = buy ? int64(currentPrice) - int64(openPrice) : int64(openPrice) - int64(currentPrice); int256 nominator = int256(priceDiff) * int256(FRACTION_SCALE) * int256(int64(leverage)); int256 longF = nominator / int256(LEVERAGE_SCALE) / int256(int64(openPrice)); f = int64(longF); f = f > maxPnlF ? maxPnlF : f; } function calculatePriceDiffFromFractionAndLeverage( uint64 originPrice, uint64 fractionDiff, uint64 leverage ) internal pure returns (uint64) { uint64 diffInPrice = uint64( (uint256(originPrice) * uint256(fractionDiff) * LEVERAGE_SCALE) / FRACTION_SCALE / uint256(leverage) ); return diffInPrice; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @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. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ 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]. * * CAUTION: See Security Considerations above. */ 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 v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../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; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @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); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // 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 FailedInnerCall(); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./AcceptableImplementationClaimableAdminStorage.sol"; /** * @title SafeUpgradeableClaimableAdmin * @dev based on Compound's Unitroller * https://github.com/compound-finance/compound-protocol/blob/a3214f67b73310d547e00fc578e8355911c9d376/contracts/Unitroller.sol */ contract AcceptableImplementationClaimableAdmin is AcceptableImplementationClaimableAdminStorage { /** * @notice Emitted when pendingImplementation is changed */ event NewPendingImplementation( address oldPendingImplementation, address newPendingImplementation ); /** * @notice Emitted when pendingImplementation is accepted, which means delegation implementation is updated */ event NewImplementation(address oldImplementation, address newImplementation); /** * @notice Emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /*** Admin Functions ***/ function _setPendingImplementation(address newPendingImplementation) public { require(msg.sender == admin, "not admin"); require( approvePendingImplementationInternal(newPendingImplementation), "INVALID_IMPLEMENTATION" ); address oldPendingImplementation = pendingImplementation; pendingImplementation = newPendingImplementation; emit NewPendingImplementation( oldPendingImplementation, pendingImplementation ); } /** * @notice Accepts new implementation. msg.sender must be pendingImplementation * @dev Admin function for new implementation to accept it's role as implementation */ function _acceptImplementation() public returns (uint) { // Check caller is pendingImplementation and pendingImplementation ≠ address(0) require( msg.sender == pendingImplementation && pendingImplementation != address(0), "Not the EXISTING pending implementation" ); // Save current values for inclusion in log address oldImplementation = implementation; address oldPendingImplementation = pendingImplementation; implementation = pendingImplementation; pendingImplementation = address(0); emit NewImplementation(oldImplementation, implementation); emit NewPendingImplementation( oldPendingImplementation, pendingImplementation ); return 0; } /** * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @param newPendingAdmin New pending admin. */ function _setPendingAdmin(address newPendingAdmin) public { // Check caller = admin require(msg.sender == admin, "Not Admin"); // Save current value, if any, for inclusion in log address oldPendingAdmin = pendingAdmin; // Store pendingAdmin with value newPendingAdmin pendingAdmin = newPendingAdmin; // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); } /** * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin * @dev Admin function for pending admin to accept role and update admin */ function _acceptAdmin() public { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) require( msg.sender == pendingAdmin && pendingAdmin != address(0), "Not the EXISTING pending admin" ); // Save current values for inclusion in log address oldAdmin = admin; address oldPendingAdmin = pendingAdmin; // Store admin with value pendingAdmin admin = pendingAdmin; // Clear the pending value pendingAdmin = address(0); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); } constructor(address _initialAdmin) { admin = _initialAdmin; emit NewAdmin(address(0), _initialAdmin); } /** * @dev Delegates execution to an implementation contract. * It returns to the external caller whatever the implementation returns * or forwards reverts. */ fallback() external payable { // delegate all other functions to current implementation (bool success, ) = implementation.delegatecall(msg.data); assembly { let free_mem_ptr := mload(0x40) returndatacopy(free_mem_ptr, 0, returndatasize()) switch success case 0 { revert(free_mem_ptr, returndatasize()) } default { return(free_mem_ptr, returndatasize()) } } } receive() external payable {} function approvePendingImplementationInternal( address // _implementation ) internal virtual returns (bool) { return true; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; contract ClaimableAdminStorage { /** * @notice Administrator for this contract */ address public admin; /** * @notice Pending administrator for this contract */ address public pendingAdmin; /*** Modifiers ***/ modifier onlyAdmin() { require(msg.sender == admin, "ONLY_ADMIN"); _; } /*** Constructor ***/ constructor() { // Set admin to caller admin = msg.sender; } } contract AcceptableImplementationClaimableAdminStorage is ClaimableAdminStorage { /** * @notice Active logic */ address public implementation; /** * @notice Pending logic */ address public pendingImplementation; } contract AcceptableRegistryImplementationClaimableAdminStorage is AcceptableImplementationClaimableAdminStorage { /** * @notice System Registry */ address public registry; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./AcceptableImplementationClaimableAdmin.sol"; import "./IContractRegistryBase.sol"; /** * @title AcceptableRegistryImplementationClaimableAdmin */ contract AcceptableRegistryImplementationClaimableAdmin is AcceptableImplementationClaimableAdmin, AcceptableRegistryImplementationClaimableAdminStorage { bytes32 public immutable CONTRACT_NAME_HASH; constructor( address _registry, string memory proxyName, address _initialAdmin ) AcceptableImplementationClaimableAdmin(_initialAdmin) { registry = _registry; CONTRACT_NAME_HASH = keccak256(abi.encodePacked(proxyName)); } function approvePendingImplementationInternal( address _implementation ) internal view override returns (bool) { return IContractRegistryBase(registry).isImplementationValidForProxy( CONTRACT_NAME_HASH, _implementation ); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IContractRegistryBase { function isImplementationValidForProxy( bytes32 proxyNameHash, address _implementation ) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.24; /** * @dev only use immutables and constants in this contract */ contract CommonScales { uint256 public constant PRECISION = 1e18; // 18 decimals uint256 public constant LEVERAGE_SCALE = 100; // 2 decimal points uint256 public constant FRACTION_SCALE = 100000; // 5 decimal points uint256 public constant ACCURACY_IMPROVEMENT_SCALE = 1e9; function calculateLeveragedPosition( uint256 collateral, uint256 leverage ) internal pure returns (uint256) { return (collateral * leverage) / LEVERAGE_SCALE; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IFundingRateModel { // return value is the "funding paid by heavier side" in PRECISION per OI (heavier side) per second // e.g : (0.01 * PRECISION) = Paying (heavier) side (as a whole) pays 1% of funding per second for each OI unit function getFundingRate( uint256 pairId, uint256 openInterestLong, uint256 openInterestShort, uint256 pairMaxOpenInterest ) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IGlobalLock { function lock() external; function freeLock() external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IInterestRateModel { // Returns asset/second of interest per borrowed unit // e.g : (0.01 * PRECISION) = 1% of interest per second function getBorrowRate(uint256 utilization) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./LexErrors.sol"; import "./LexPoolAdminEnums.sol"; import "./IPoolAccountantV1.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface LexPoolStructs { struct PendingDeposit { uint256 amount; uint256 minAmountOut; } struct PendingRedeem { uint256 amount; uint256 minAmountOut; uint256 maxAmountOut; } } interface LexPoolEvents is LexPoolAdminEnums { event NewEpoch( uint256 epochId, int256 reportedUnrealizedPricePnL, uint256 exchangeRate, uint256 virtualUnderlyingBalance, uint256 totalSupply ); event AddressUpdated(LexPoolAddressesEnum indexed enumCode, address a); event NumberUpdated(LexPoolNumbersEnum indexed enumCode, uint value); event DepositRequest( address indexed user, uint256 amount, uint256 minAmountOut, uint256 processingEpoch ); event RedeemRequest( address indexed user, uint256 amount, uint256 minAmountOut, uint256 processingEpoch ); event ProcessedDeposit( address indexed user, bool deposited, uint256 depositedAmount ); event ProcessedRedeem( address indexed user, bool redeemed, uint256 withdrawnAmount // Underlying amount ); event CanceledDeposit( address indexed user, uint256 epoch, uint256 cancelledAmount ); event CanceledRedeem( address indexed user, uint256 epoch, uint256 cancelledAmount ); event ImmediateDepositAllowedToggled(bool indexed value); event ImmediateDeposit( address indexed depositor, uint256 depositAmount, uint256 mintAmount ); event ReservesWithdrawn( address _to, uint256 interestShare, uint256 totalFundingShare ); } interface ILexPoolFunctionality is IERC20, LexPoolStructs, LexPoolEvents, LexErrors { function setPoolAccountant( IPoolAccountantFunctionality _poolAccountant ) external; function setPnlRole(address pnl) external; function setMaxExtraWithdrawalAmountF(uint256 maxExtra) external; function setEpochsDelayDeposit(uint256 delay) external; function setEpochsDelayRedeem(uint256 delay) external; function setEpochDuration(uint256 duration) external; function setMinDepositAmount(uint256 amount) external; function toggleImmediateDepositAllowed() external; function reduceReserves( address _to ) external returns (uint256 interestShare, uint256 totalFundingShare); function requestDeposit( uint256 amount, uint256 minAmountOut, bytes32 domain, bytes32 referralCode ) external; function requestDepositViaIntent( address user, uint256 amount, uint256 minAmountOut, bytes32 domain, bytes32 referralCode ) external; function requestRedeem(uint256 amount, uint256 minAmountOut) external; function requestRedeemViaIntent( address user, uint256 amount, uint256 minAmountOut ) external; function processDeposit( address[] memory users ) external returns ( uint256 amountDeposited, uint256 amountCancelled, uint256 counterDeposited, uint256 counterCancelled ); function cancelDeposits( address[] memory users, uint256[] memory epochs ) external; function processRedeems( address[] memory users ) external returns ( uint256 amountRedeemed, uint256 amountCancelled, uint256 counterDeposited, uint256 counterCancelled ); function cancelRedeems( address[] memory users, uint256[] memory epochs ) external; function nextEpoch( int256 totalUnrealizedPricePnL ) external returns (uint256 newExchangeRate); function currentVirtualUtilization() external view returns (uint256); function currentVirtualUtilization( uint256 totalBorrows, uint256 totalReserves, int256 unrealizedFunding ) external view returns (uint256); function virtualBalanceForUtilization() external view returns (uint256); function virtualBalanceForUtilization( uint256 extraAmount, int256 unrealizedFunding ) external view returns (uint256); function underlyingBalanceForExchangeRate() external view returns (uint256); function sendAssetToTrader(address to, uint256 amount) external; function isUtilizationForLPsValid() external view returns (bool); } interface ILexPoolV1 is ILexPoolFunctionality { function name() external view returns (string memory); function symbol() external view returns (string memory); function SELF_UNIT_SCALE() external view returns (uint); function underlyingDecimals() external view returns (uint256); function poolAccountant() external view returns (address); function underlying() external view returns (IERC20); function tradingFloor() external view returns (address); function currentEpoch() external view returns (uint256); function currentExchangeRate() external view returns (uint256); function nextEpochStartMin() external view returns (uint256); function epochDuration() external view returns (uint256); function minDepositAmount() external view returns (uint256); function epochsDelayDeposit() external view returns (uint256); function epochsDelayRedeem() external view returns (uint256); function immediateDepositAllowed() external view returns (bool); function pendingDeposits( uint epoch, address account ) external view returns (PendingDeposit memory); function pendingRedeems( uint epoch, address account ) external view returns (PendingRedeem memory); function pendingDepositAmount() external view returns (uint256); function pendingWithdrawalAmount() external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./LexErrors.sol"; import "./ILexPoolV1.sol"; import "./IInterestRateModel.sol"; import "./IFundingRateModel.sol"; import "./TradingEnumsV1.sol"; interface PoolAccountantStructs { // @note To be used for passing information in function calls struct PositionRegistrationParams { uint256 collateral; uint32 leverage; bool long; uint64 openPrice; uint64 tp; } struct PairFunding { // Slot 0 int256 accPerOiLong; // 32 bytes -- Underlying Decimals // Slot 1 int256 accPerOiShort; // 32 bytes -- Underlying Decimals // Slot 2 uint256 lastUpdateTimestamp; // 32 bytes } struct TradeInitialAccFees { // Slot 0 uint256 borrowIndex; // 32 bytes // Slot 1 int256 funding; // 32 bytes -- underlying units -- Underlying Decimals } struct PairOpenInterest { // Slot 0 uint256 long; // 32 bytes -- underlying units -- Dynamic open interest for long positions // Slot 1 uint256 short; // 32 bytes -- underlying units -- Dynamic open interest for short positions } // This struct is not kept in storage struct PairFromTo { string from; string to; } struct Pair { // Slot 0 uint16 id; // 02 bytes uint16 groupId; // 02 bytes uint16 feeId; // 02 bytes uint32 minLeverage; // 04 bytes uint32 maxLeverage; // 04 bytes uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5) // Slot 1 uint256 maxPositionSize; // 32 bytes -- underlying units // Slot 2 uint256 maxGain; // 32 bytes -- underlying units // Slot 3 uint256 maxOpenInterest; // 32 bytes -- Underlying units // Slot 4 uint256 maxSkew; // 32 bytes -- underlying units // Slot 5 uint256 minOpenFee; // 32 bytes -- underlying units. MAX_UINT means use the default group level value // Slot 6 uint256 minPerformanceFee; // 32 bytes -- underlying units } struct Group { // Slot 0 uint16 id; // 02 bytes uint32 minLeverage; // 04 bytes uint32 maxLeverage; // 04 bytes uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5) // Slot 1 uint256 maxPositionSize; // 32 bytes (Underlying units) // Slot 2 uint256 minOpenFee; // 32 bytes (Underlying uints). MAX_UINT means use the default global level value } struct Fee { // Slot 0 uint16 id; // 02 bytes uint32 openFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos) uint32 closeFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos) uint32 performanceFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of performance) } } interface PoolAccountantEvents is PoolAccountantStructs { event PairAdded( uint256 indexed id, string indexed from, string indexed to, Pair pair ); event PairUpdated(uint256 indexed id, Pair pair); event GroupAdded(uint256 indexed id, string indexed groupName, Group group); event GroupUpdated(uint256 indexed id, Group group); event FeeAdded(uint256 indexed id, string indexed name, Fee fee); event FeeUpdated(uint256 indexed id, Fee fee); event TradeInitialAccFeesStored( bytes32 indexed positionId, uint256 borrowIndex, // uint256 rollover, int256 funding ); event AccrueFunding( uint256 indexed pairId, int256 valueLong, int256 valueShort ); event ProtocolFundingShareAccrued( uint16 indexed pairId, uint256 protocolFundingShare ); // event AccRolloverFeesStored(uint256 pairIndex, uint256 value); event FeesCharged( bytes32 indexed positionId, address indexed trader, uint16 indexed pairId, PositionRegistrationParams positionRegistrationParams, // bool long, // uint256 collateral, // Underlying Decimals // uint256 leverage, int256 profitPrecision, // PRECISION uint256 interest, int256 funding, // Underlying Decimals uint256 closingFee, uint256 tradeValue ); event PerformanceFeeCharging( bytes32 indexed positionId, uint256 performanceFee ); event MaxOpenInterestUpdated(uint256 pairIndex, uint256 maxOpenInterest); event AccrueInterest( uint256 cash, uint256 totalInterestNew, uint256 borrowIndexNew, uint256 interestShareNew ); event Borrow( uint256 indexed pairId, uint256 borrowAmount, uint256 newTotalBorrows ); event Repay( uint256 indexed pairId, uint256 repayAmount, uint256 newTotalBorrows ); } interface IPoolAccountantFunctionality is PoolAccountantStructs, PoolAccountantEvents, LexErrors, TradingEnumsV1 { function setTradeIncentivizer(address _tradeIncentivizer) external; function setMaxGainF(uint256 _maxGainF) external; function setFrm(IFundingRateModel _frm) external; function setMinOpenFee(uint256 min) external; function setLexPartF(uint256 partF) external; function setFundingRateMax(uint256 maxValue) external; function setLiquidationThresholdF(uint256 threshold) external; function setLiquidationFeeF(uint256 fee) external; function setIrm(IInterestRateModel _irm) external; function setIrmHard(IInterestRateModel _irm) external; function setInterestShareFactor(uint256 factor) external; function setFundingShareFactor(uint256 factor) external; function setBorrowRateMax(uint256 rate) external; function setMaxTotalBorrows(uint256 maxBorrows) external; function setMaxVirtualUtilization(uint256 _maxVirtualUtilization) external; function resetTradersPairGains(uint256 pairId) external; function addGroup(Group calldata _group) external; function updateGroup(Group calldata _group) external; function addFee(Fee calldata _fee) external; function updateFee(Fee calldata _fee) external; function addPair(Pair calldata _pair) external; function addPairs(Pair[] calldata _pairs) external; function updatePair(Pair calldata _pair) external; function readAndZeroReserves() external returns (uint256 accumulatedInterestShare, uint256 accFundingShare); function registerOpenTrade( bytes32 positionId, address trader, uint16 pairId, uint256 collateral, uint32 leverage, bool long, uint256 tp, uint256 openPrice ) external returns (uint256 fee, uint256 lexPartFee); function registerCloseTrade( bytes32 positionId, address trader, uint16 pairId, PositionRegistrationParams calldata positionRegistrationParams, uint256 closePrice, PositionCloseType positionCloseType ) external returns ( uint256 closingFee, uint256 tradeValue, int256 profitPrecision, uint finalClosePrice ); function registerUpdateTp( bytes32 positionId, address trader, uint16 pairId, uint256 collateral, uint32 leverage, bool long, uint256 openPrice, uint256 oldTriggerPrice, uint256 triggerPrice ) external; // function registerUpdateSl( // address trader, // uint256 pairIndex, // uint256 index, // uint256 collateral, // uint256 leverage, // bool long, // uint256 openPrice, // uint256 triggerPrice // ) external returns (uint256 fee); function accrueInterest() external returns ( uint256 totalInterestNew, uint256 interestShareNew, uint256 borrowIndexNew ); // Limited only for the LexPool function accrueInterest( uint256 availableCash ) external returns ( uint256 totalInterestNew, uint256 interestShareNew, uint256 borrowIndexNew ); function getTradeClosingValues( bytes32 positionId, uint16 pairId, PositionRegistrationParams calldata positionRegistrationParams, uint256 closePrice, bool isLiquidation ) external returns ( uint256 tradeValue, // Underlying Decimals uint256 safeClosingFee, int256 profitPrecision, uint256 interest, int256 funding ); function getTradeLiquidationPrice( bytes32 positionId, uint16 pairId, uint256 openPrice, // PRICE_SCALE (8) uint256 tp, bool long, uint256 collateral, // Underlying Decimals uint32 leverage ) external returns ( uint256 // PRICE_SCALE (8) ); function calcTradeDynamicFees( bytes32 positionId, uint16 pairId, bool long, uint256 collateral, uint32 leverage, uint256 openPrice, uint256 tp ) external returns (uint256 interest, int256 funding); function unrealizedFunding() external view returns (int256); function totalBorrows() external view returns (uint256); function interestShare() external view returns (uint256); function fundingShare() external view returns (uint256); function totalReservesView() external view returns (uint256); function borrowsAndInterestShare() external view returns (uint256 totalBorrows, uint256 totalInterestShare); function pairTotalOpenInterest( uint256 pairIndex ) external view returns (int256); function pricePnL( uint256 pairId, uint256 price ) external view returns (int256); function getAllSupportedPairIds() external view returns (uint16[] memory); function getAllSupportedGroupsIds() external view returns (uint16[] memory); function getAllSupportedFeeIds() external view returns (uint16[] memory); } interface IPoolAccountantV1 is IPoolAccountantFunctionality { function totalBorrows() external view returns (uint256); function maxTotalBorrows() external view returns (uint256); function pairBorrows(uint256 pairId) external view returns (uint256); function groupBorrows(uint256 groupId) external view returns (uint256); function pairMaxBorrow(uint16 pairId) external view returns (uint256); function groupMaxBorrow(uint16 groupId) external view returns (uint256); function lexPool() external view returns (ILexPoolV1); function maxGainF() external view returns (uint256); function interestShareFactor() external view returns (uint256); function fundingShareFactor() external view returns (uint256); function frm() external view returns (IFundingRateModel); function irm() external view returns (IInterestRateModel); function pairs(uint16 pairId) external view returns (Pair memory); function groups(uint16 groupId) external view returns (Group memory); function fees(uint16 feeId) external view returns (Fee memory); function openInterestInPair( uint pairId ) external view returns (PairOpenInterest memory); function minOpenFee() external view returns (uint256); function liquidationThresholdF() external view returns (uint256); function liquidationFeeF() external view returns (uint256); function lexPartF() external view returns (uint256); function tradersPairGains(uint256 pairId) external view returns (int256); function calcBorrowAmount( uint256 collateral, uint256 leverage, bool long, uint256 openPrice, uint256 tp ) external pure returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "../../AdministrationContracts/IContractRegistryBase.sol"; import "./IGlobalLock.sol"; interface IRegistryV1Functionality is IContractRegistryBase, IGlobalLock { // **** Locking mechanism **** function isTradersPortalAndLocker( address _address ) external view returns (bool); function isTriggersAndLocker(address _address) external view returns (bool); function isTradersPortalOrTriggersAndLocker( address _address ) external view returns (bool); } interface IRegistryV1 is IRegistryV1Functionality { // **** Public Storage params **** function feesManagers(address asset) external view returns (address); function orderBook() external view returns (address); function tradersPortal() external view returns (address); function triggers() external view returns (address); function tradeIntentsVerifier() external view returns (address); function liquidityIntentsVerifier() external view returns (address); function chipsIntentsVerifier() external view returns (address); function lexProxiesFactory() external view returns (address); function chipsFactory() external view returns (address); /** * @return An array of all supported trading floors */ function getAllSupportedTradingFloors() external view returns (address[] memory); /** * @return An array of all supported settlement assets */ function getSettlementAssetsForTradingFloor( address _tradingFloor ) external view returns (address[] memory); /** * @return The spender role address that is set for this chip */ function getValidSpenderTargetForChipByRole( address chip, string calldata role ) external view returns (address); /** * @return the address of the valid 'burnHandler' for the chip */ function validBurnHandlerForChip( address chip ) external view returns (address); /** * @return The address matching for the given role */ function getDynamicRoleAddress( string calldata _role ) external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./TradingFloorStructsV1.sol"; import "./IPoolAccountantV1.sol"; import "./ILexPoolV1.sol"; interface ITradingFloorV1Functionality is TradingFloorStructsV1 { function supportNewSettlementAsset( address _asset, address _lexPool, address _poolAccountant ) external; function getPositionTriggerInfo( bytes32 _positionId ) external view returns ( PositionPhase positionPhase, uint64 timestamp, uint16 pairId, bool long, uint32 spreadReductionF ); function getPositionPortalInfo( bytes32 _positionId ) external view returns ( PositionPhase positionPhase, uint64 inPhaseSince, address positionTrader ); function storePendingPosition( OpenOrderType _orderType, PositionRequestIdentifiers memory _requestIdentifiers, PositionRequestParams memory _requestParams, uint32 _spreadReductionF ) external returns (bytes32 positionId); function setOpenedPositionToMarketClose( bytes32 _positionId, uint64 _minPrice, uint64 _maxPrice ) external; function cancelPendingPosition( bytes32 _positionId, OpenOrderType _orderType, uint feeFraction ) external; function cancelMarketCloseForPosition( bytes32 _positionId, CloseOrderType _orderType, uint feeFraction ) external; function updatePendingPosition_openLimit( bytes32 _positionId, uint64 _minPrice, uint64 _maxPrice, uint64 _tp, uint64 _sl ) external; function openNewPosition_market( bytes32 _positionId, uint64 assetEffectivePrice, uint256 feeForCancellation ) external; function openNewPosition_limit( bytes32 _positionId, uint64 assetEffectivePrice, uint256 feeForCancellation ) external; function closeExistingPosition_Market( bytes32 _positionId, uint64 assetPrice, uint64 effectivePrice ) external; function closeExistingPosition_Limit( bytes32 _positionId, LimitTrigger limitTrigger, uint64 assetPrice, uint64 effectivePrice ) external; // Manage open trade function updateOpenedPosition( bytes32 _positionId, PositionField updateField, uint64 fieldValue, uint64 effectivePrice ) external; // Fees function collectFee(address _asset, FeeType _feeType, address _to) external; } interface ITradingFloorV1 is ITradingFloorV1Functionality { function PRECISION() external pure returns (uint); // *** Views *** function pairTradersArray( address _asset, uint _pairIndex ) external view returns (address[] memory); function generatePositionHashId( address settlementAsset, address trader, uint16 pairId, uint32 index ) external pure returns (bytes32 hashId); // *** Public Storage addresses *** function lexPoolForAsset(address asset) external view returns (ILexPoolV1); function poolAccountantForAsset( address asset ) external view returns (IPoolAccountantV1); function registry() external view returns (address); // *** Public Storage params *** function positionsById(bytes32 id) external view returns (Position memory); function positionIdentifiersById( bytes32 id ) external view returns (PositionIdentifiers memory); function positionLimitsInfoById( bytes32 id ) external view returns (PositionLimitsInfo memory); function triggerPricesById( bytes32 id ) external view returns (PositionTriggerPrices memory); function pairTradersInfo( address settlementAsset, address trader, uint pairId ) external view returns (PairTraderInfo memory); function spreadReductionsP(uint) external view returns (uint); function maxSlF() external view returns (uint); function maxTradesPerPair() external view returns (uint); function maxSanityProfitF() external view returns (uint); function feesMap( address settlementAsset, FeeType feeType ) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface LexErrors { enum CapType { NONE, // 0 MIN_OPEN_FEE, // 1 MAX_POS_SIZE_PAIR, // 2 MAX_POS_SIZE_GROUP, // 3 MAX_LEVERAGE, // 4 MIN_LEVERAGE, // 5 MAX_VIRTUAL_UTILIZATION, // 6 MAX_OPEN_INTEREST, // 7 MAX_ABS_SKEW, // 8 MAX_BORROW_PAIR, // 9 MAX_BORROW_GROUP, // 10 MIN_DEPOSIT_AMOUNT, // 11 MAX_ACCUMULATED_GAINS, // 12 BORROW_RATE_MAX, // 13 FUNDING_RATE_MAX, // 14 MAX_POTENTIAL_GAIN, // 15 MAX_TOTAL_BORROW, // 16 MIN_PERFORMANCE_FEE // 17 //... } error CapError(CapType, uint256 value); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.24; interface LexPoolAdminEnums { enum LexPoolAddressesEnum { none, poolAccountant, pnlRole } enum LexPoolNumbersEnum { none, maxExtraWithdrawalAmountF, epochsDelayDeposit, epochsDelayRedeem, epochDuration, minDepositAmount } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface TradingEnumsV1 { enum PositionPhase { NONE, OPEN_MARKET, OPEN_LIMIT, OPENED, CLOSE_MARKET, CLOSED } enum OpenOrderType { NONE, MARKET, LIMIT } enum CloseOrderType { NONE, MARKET } enum FeeType { NONE, OPEN_FEE, CLOSE_FEE, TRIGGER_FEE } enum LimitTrigger { NONE, TP, SL, LIQ } enum PositionField { NONE, TP, SL } enum PositionCloseType { NONE, TP, SL, LIQ, MARKET } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./TradingEnumsV1.sol"; interface TradingFloorStructsV1 is TradingEnumsV1 { enum AdminNumericParam { NONE, MAX_TRADES_PER_PAIR, MAX_SL_F, MAX_SANITY_PROFIT_F } /** * @dev Memory struct for identifiers */ struct PositionRequestIdentifiers { address trader; uint16 pairId; address settlementAsset; uint32 positionIndex; } struct PositionRequestParams { bool long; uint256 collateral; // Settlement Asset Decimals uint32 leverage; uint64 minPrice; // PRICE_SCALE uint64 maxPrice; // PRICE_SCALE uint64 tp; // PRICE_SCALE uint64 sl; // PRICE_SCALE uint64 tpByFraction; // FRACTION_SCALE uint64 slByFraction; // FRACTION_SCALE } /** * @dev Storage struct for identifiers */ struct PositionIdentifiers { // Slot 0 address settlementAsset; // 20 bytes uint16 pairId; // 02 bytes uint32 index; // 04 bytes // Slot 1 address trader; // 20 bytes } struct Position { // Slot 0 uint collateral; // 32 bytes -- Settlement Asset Decimals // Slot 1 PositionPhase phase; // 01 bytes uint64 inPhaseSince; // 08 bytes uint32 leverage; // 04 bytes bool long; // 01 bytes uint64 openPrice; // 08 bytes -- PRICE_SCALE (8) uint32 spreadReductionF; // 04 bytes -- FRACTION_SCALE (5) } /** * Holds the non liquidation limits for the position */ struct PositionLimitsInfo { uint64 tpLastUpdated; // 08 bytes -- timestamp uint64 slLastUpdated; // 08 bytes -- timestamp uint64 tp; // 08 bytes -- PRICE_SCALE (8) uint64 sl; // 08 bytes -- PRICE_SCALE (8) } /** * Holds the prices for opening (and market closing) of a position */ struct PositionTriggerPrices { uint64 minPrice; // 08 bytes -- PRICE_SCALE uint64 maxPrice; // 08 bytes -- PRICE_SCALE uint64 tpByFraction; // 04 bytes -- FRACTION_SCALE uint64 slByFraction; // 04 bytes -- FRACTION_SCALE } /** * @dev administration struct, used to keep tracks on the 'PairTraders' list and * to limit the amount of positions a trader can have */ struct PairTraderInfo { uint32 positionsCounter; // 04 bytes uint32 positionInArray; // 04 bytes (the index + 1) // Note : Can add more fields here } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "../../AdministrationContracts/AcceptableRegistryImplementationClaimableAdmin.sol"; /** * @title TradingFloorProxy * @dev Used as the upgradable brain of the Lynx platform */ contract TradingFloorProxy is AcceptableRegistryImplementationClaimableAdmin { constructor( address _registry ) AcceptableRegistryImplementationClaimableAdmin( _registry, "TradingFloor", msg.sender ) {} }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "../../AdministrationContracts/AcceptableImplementationClaimableAdminStorage.sol"; import "../interfaces/ITradingFloorV1.sol"; import "../Common/CommonScales.sol"; /** * @title TradingFloorStorageV1 * @dev Storage contract for the TradingFloor */ contract TradingFloorV1Storage is AcceptableRegistryImplementationClaimableAdminStorage, TradingFloorStructsV1, CommonScales { // ***** Trading variables ***** uint public maxTradesPerPair; uint public maxSlF; // FRACTION_SCALE (5) uint public maxSanityProfitF; // FRACTION_SCALE (5) // ***** Pair pausing ***** mapping(uint => bool) public pausedPairs; // ***** Fees ***** // Token => Fee Type => Amount mapping(address => mapping(FeeType => uint)) public feesMap; // ***** Lex&Accountant ***** // settlement asset => lex pool mapping(address => address) public lexPoolForAsset; // settlement asset => pool accountant mapping(address => address) public poolAccountantForAsset; // ***** Position Identifiers ***** // position id => PositionIdentifiers struct mapping(bytes32 => PositionIdentifiers) public positionIdentifiersById; // ***** Positions ***** // position id => Position Struct mapping(bytes32 => Position) public positionsById; // position id => OpenTradeInfo struct mapping(bytes32 => PositionLimitsInfo) public positionLimitsInfoById; // position id => trigger prices mapping(bytes32 => PositionTriggerPrices) public triggerPricesById; // Position id => initial collateral mapping(bytes32 => uint) public initialCollateralByPositionId; // asset => pair id => traders list mapping(address => mapping(uint => address[])) public pairTraders; // asset => trader => pair id => index in traders list mapping(address => mapping(address => mapping(uint => PairTraderInfo))) public pairTradersInfo; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"enum LexErrors.CapType","name":"","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"CapError","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"enum TradingEnumsV1.FeeType","name":"feeType","type":"uint8"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"enum TradingEnumsV1.FeeType","name":"feeType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"NumberUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"},{"indexed":false,"internalType":"bool","name":"buy","type":"bool"},{"indexed":true,"internalType":"enum TradingEnumsV1.PositionField","name":"updatedField","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"fieldValue","type":"uint64"}],"name":"OpenedPositionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pairId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PairPausedChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"PendingPositionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"enum TradingEnumsV1.PositionPhase","name":"phase","type":"uint8"},{"components":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"address","name":"settlementAsset","type":"address"},{"internalType":"uint32","name":"positionIndex","type":"uint32"}],"indexed":false,"internalType":"struct TradingFloorStructsV1.PositionRequestIdentifiers","name":"requestIdentifiers","type":"tuple"},{"components":[{"internalType":"bool","name":"long","type":"bool"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint32","name":"leverage","type":"uint32"},{"internalType":"uint64","name":"minPrice","type":"uint64"},{"internalType":"uint64","name":"maxPrice","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"},{"internalType":"uint64","name":"sl","type":"uint64"},{"internalType":"uint64","name":"tpByFraction","type":"uint64"},{"internalType":"uint64","name":"slByFraction","type":"uint64"}],"indexed":false,"internalType":"struct TradingFloorStructsV1.PositionRequestParams","name":"requestParams","type":"tuple"},{"indexed":false,"internalType":"uint32","name":"_spreadReductionF","type":"uint32"}],"name":"PendingPositionStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"tp","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"sl","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"minPrice","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"maxPrice","type":"uint64"}],"name":"PendingPositionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum TradingEnumsV1.LimitTrigger","name":"limitTrigger","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"effectiveClosePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tradeValue","type":"uint256"},{"indexed":false,"internalType":"int256","name":"profitPrecision","type":"int256"}],"name":"PositionClosedLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tradeValue","type":"uint256"},{"indexed":false,"internalType":"int256","name":"profitPrecision","type":"int256"}],"name":"PositionClosedMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"components":[{"internalType":"address","name":"settlementAsset","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"address","name":"trader","type":"address"}],"indexed":false,"internalType":"struct TradingFloorStructsV1.PositionIdentifiers","name":"identifiers","type":"tuple"}],"name":"PositionIdentifiersStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"PositionMarketCloseCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"enum LexErrors.CapType","name":"capType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"PositionOpenCancelledByCap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"triggerPrice","type":"uint64"}],"name":"PositionOpenCancelledByMarketPriceRange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"openPrice","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"tp","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"sl","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"totalOpenFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lexFeePart","type":"uint256"}],"name":"PositionOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"_minPrice","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"_maxPrice","type":"uint64"}],"name":"PositionSetForMarketClose","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"lexPool","type":"address"},{"indexed":true,"internalType":"address","name":"poolAccountant","type":"address"}],"name":"SettlementAssetAdded","type":"event"},{"inputs":[],"name":"ACCURACY_IMPROVEMENT_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRACTION_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVERAGE_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE_FRACTION_FOR_CANCEL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract TradingFloorProxy","name":"tradingFloorProxy","type":"address"}],"name":"_become","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"enum TradingEnumsV1.CloseOrderType","name":"_orderType","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"cancelMarketCloseForPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"enum TradingEnumsV1.OpenOrderType","name":"_orderType","type":"uint8"},{"internalType":"uint256","name":"feeFraction","type":"uint256"}],"name":"cancelPendingPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"enum TradingEnumsV1.LimitTrigger","name":"limitTrigger","type":"uint8"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"effectivePrice","type":"uint64"}],"name":"closeExistingPosition_Limit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"effectivePrice","type":"uint64"}],"name":"closeExistingPosition_Market","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"enum TradingEnumsV1.FeeType","name":"_feeType","type":"uint8"},{"internalType":"address","name":"_to","type":"address"}],"name":"collectFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"enum TradingEnumsV1.FeeType","name":"","type":"uint8"}],"name":"feesMap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"settlementAsset","type":"address"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"uint32","name":"index","type":"uint32"}],"name":"generatePositionHashId","outputs":[{"internalType":"bytes32","name":"hashId","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPositionPortalInfo","outputs":[{"internalType":"enum TradingEnumsV1.PositionPhase","name":"positionPhase","type":"uint8"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"address","name":"trader","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPositionRegistrationParams","outputs":[{"components":[{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint32","name":"leverage","type":"uint32"},{"internalType":"bool","name":"long","type":"bool"},{"internalType":"uint64","name":"openPrice","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"}],"internalType":"struct PoolAccountantStructs.PositionRegistrationParams","name":"registrationParams","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPositionTriggerInfo","outputs":[{"internalType":"enum TradingEnumsV1.PositionPhase","name":"positionPhase","type":"uint8"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"bool","name":"long","type":"bool"},{"internalType":"uint32","name":"spreadReductionF","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"initialCollateralByPositionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"settlementAsset","type":"address"}],"name":"isSettlementAssetSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lexPoolForAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSanityProfitF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSlF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTradesPerPair","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"uint64","name":"assetEffectivePrice","type":"uint64"},{"internalType":"uint256","name":"feeForCancellation","type":"uint256"}],"name":"openNewPosition_limit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"uint64","name":"assetEffectivePrice","type":"uint64"},{"internalType":"uint256","name":"feeForCancellation","type":"uint256"}],"name":"openNewPosition_market","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pairTraders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_pairIndex","type":"uint256"}],"name":"pairTradersArray","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pairTradersInfo","outputs":[{"internalType":"uint32","name":"positionsCounter","type":"uint32"},{"internalType":"uint32","name":"positionInArray","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pausedPairs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolAccountantForAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positionIdentifiersById","outputs":[{"internalType":"address","name":"settlementAsset","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"address","name":"trader","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positionLimitsInfoById","outputs":[{"internalType":"uint64","name":"tpLastUpdated","type":"uint64"},{"internalType":"uint64","name":"slLastUpdated","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"},{"internalType":"uint64","name":"sl","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positionsById","outputs":[{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"enum TradingEnumsV1.PositionPhase","name":"phase","type":"uint8"},{"internalType":"uint64","name":"inPhaseSince","type":"uint64"},{"internalType":"uint32","name":"leverage","type":"uint32"},{"internalType":"bool","name":"long","type":"bool"},{"internalType":"uint64","name":"openPrice","type":"uint64"},{"internalType":"uint32","name":"spreadReductionF","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"uint64","name":"_minPrice","type":"uint64"},{"internalType":"uint64","name":"_maxPrice","type":"uint64"}],"name":"setOpenedPositionToMarketClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pairId","type":"uint256"},{"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"setPairPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum TradingFloorStructsV1.AdminNumericParam","name":"numericParam","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setTradeParam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum TradingEnumsV1.OpenOrderType","name":"_orderType","type":"uint8"},{"components":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"address","name":"settlementAsset","type":"address"},{"internalType":"uint32","name":"positionIndex","type":"uint32"}],"internalType":"struct TradingFloorStructsV1.PositionRequestIdentifiers","name":"_requestIdentifiers","type":"tuple"},{"components":[{"internalType":"bool","name":"long","type":"bool"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint32","name":"leverage","type":"uint32"},{"internalType":"uint64","name":"minPrice","type":"uint64"},{"internalType":"uint64","name":"maxPrice","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"},{"internalType":"uint64","name":"sl","type":"uint64"},{"internalType":"uint64","name":"tpByFraction","type":"uint64"},{"internalType":"uint64","name":"slByFraction","type":"uint64"}],"internalType":"struct TradingFloorStructsV1.PositionRequestParams","name":"_requestParams","type":"tuple"},{"internalType":"uint32","name":"_spreadReductionF","type":"uint32"}],"name":"storePendingPosition","outputs":[{"internalType":"bytes32","name":"positionId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_lexPool","type":"address"},{"internalType":"address","name":"_poolAccountant","type":"address"}],"name":"supportNewSettlementAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"triggerPricesById","outputs":[{"internalType":"uint64","name":"minPrice","type":"uint64"},{"internalType":"uint64","name":"maxPrice","type":"uint64"},{"internalType":"uint64","name":"tpByFraction","type":"uint64"},{"internalType":"uint64","name":"slByFraction","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"positionId","type":"bytes32"},{"internalType":"enum TradingEnumsV1.PositionField","name":"updateField","type":"uint8"},{"internalType":"uint64","name":"fieldValue","type":"uint64"},{"internalType":"uint64","name":"effectivePrice","type":"uint64"}],"name":"updateOpenedPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"uint64","name":"_minPrice","type":"uint64"},{"internalType":"uint64","name":"_maxPrice","type":"uint64"},{"internalType":"uint64","name":"_tp","type":"uint64"},{"internalType":"uint64","name":"_sl","type":"uint64"}],"name":"updatePendingPosition_openLimit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615a0480620000336000396000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c80638c01936e1161015c578063c07f9921116100ce578063f2eb245e11610087578063f2eb245e1461081f578063f51f3fd31461083f578063f555f69714610848578063f65d9dbe14610868578063f851a44014610871578063f9b9484e1461088457600080fd5b8063c07f992114610778578063ca3a3a821461078b578063cae290c81461079e578063ddf474f1146107b1578063e640f33b146107f9578063eb4891401461080c57600080fd5b80639ff69ffa116101205780639ff69ffa1461071d578063a2a25ea614610730578063a40d726814610743578063aaf5eb6814610756578063ad1f2b5614610765578063b71f3cfe1461076d57600080fd5b80638c01936e146105915780638f7a8fb5146105f157806393a7f6a71461066c57806394a1e6e51461069a57806395be5050146106a257600080fd5b80635c60da1b116101f557806376d901be116101b957806376d901be146105125780637b1039991461054557806380193b261461055857806380a7f3d414610562578063825714091461057557806386dc49751461057e57600080fd5b80635c60da1b14610435578063652dcb431461044857806366307a4f1461045b5780636e01af8d146104d657806374d8b78e146104e957600080fd5b806324b22a1f1161024757806324b22a1f1461039057806326782247146103a357806330d073d0146103b657806331867212146103ef578063396f7b231461040f5780634ebe5c331461042257600080fd5b806303b90a8714610284578063042e37c5146102ca57806318fa4714146103555780631d504dc61461036a5780631ea9af6b1461037d575b600080fd5b6102ad610292366004614c2a565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103196102d8366004614c47565b600c60205260009081526040902080546001909101546001600160a01b0380831692600160a01b810461ffff1692600160b01b90910463ffffffff16911684565b604080516001600160a01b03958616815261ffff909416602085015263ffffffff909216918301919091529190911660608201526080016102c1565b610368610363366004614c6d565b6108e6565b005b610368610378366004614c2a565b6109ba565b61036861038b366004614cd4565b610b08565b61036861039e366004614d09565b610b9e565b6001546102ad906001600160a01b031681565b6103e16103c4366004614d35565b600960209081526000928352604080842090915290825290205481565b6040519081526020016102c1565b6104026103fd366004614d6e565b610e3b565b6040516102c19190614d8c565b6003546102ad906001600160a01b031681565b610368610430366004614dd9565b610ebb565b6002546102ad906001600160a01b031681565b6102ad610456366004614e15565b610f7f565b6104a3610469366004614c47565b600e602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b03958616815293851660208501529184169183019190915290911660608201526080016102c1565b6103686104e4366004614e57565b610fc4565b6102ad6104f7366004614c2a565b600a602052600090815260409020546001600160a01b031681565b610535610520366004614c47565b60086020526000908152604090205460ff1681565b60405190151581526020016102c1565b6004546102ad906001600160a01b031681565b6103e1620186a081565b610368610570366004614e7e565b61135f565b6103e160075481565b61036861058c366004614ee6565b6117b7565b6105d461059f366004614f0b565b601260209081526000938452604080852082529284528284209052825290205463ffffffff8082169164010000000090041682565b6040805163ffffffff9384168152929091166020830152016102c1565b6106596105ff366004614c47565b600d602052600090815260409020805460019091015460ff808216916001600160401b03610100820481169263ffffffff600160481b8404811693600160681b810490921692600160701b83041691600160b01b90041687565b6040516102c19796959493929190614f65565b61053561067a366004614c2a565b6001600160a01b039081166000908152600a602052604090205416151590565b6103e161184a565b61070c6106b0366004614c47565b6000908152600d6020818152604080842060010154600c835293205491905260ff8083169361010084046001600160401b031693600160a01b90930461ffff1692600160681b810490921691600160b01b900463ffffffff1690565b6040516102c1959493929190614fba565b61036861072b366004614ffe565b61185b565b61036861073e36600461505c565b611aa2565b6103e16107513660046150b2565b611bc4565b6103e1670de0b6b3a764000081565b6103e1606481565b6103e1633b9aca0081565b6103686107863660046150ff565b611c33565b610368610799366004615127565b612380565b6103e16107ac366004615284565b612531565b6104a36107bf366004614c47565b600f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b610368610807366004615127565b612b10565b61036861081a366004614cd4565b612ca1565b6103e161082d366004614c47565b60106020526000908152604090205481565b6103e160065481565b61085b610856366004614c47565b612d37565b6040516102c19190615399565b6103e160055481565b6000546102ad906001600160a01b031681565b6108d7610892366004614c47565b6000908152600d60209081526040808320600190810154600c90935292209091015460ff8216926101009092046001600160401b0316916001600160a01b0390911690565b6040516102c1939291906153a7565b6004805460405163a8e36e5b60e01b81526001600160a01b038681169382019390935291169063a8e36e5b90602401602060405180830381865afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095691906153dd565b6001600160a01b0316336001600160a01b0316146109aa5760405162461bcd60e51b815260206004820152600c60248201526b10a332b2b9a6b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6109b5838383612e5f565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1c91906153dd565b6001600160a01b0316336001600160a01b031614610a6b5760405162461bcd60e51b815260206004820152600c60248201526b10b83937bc3c9730b236b4b760a11b60448201526064016109a1565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acf91906153fa565b15610b055760405162461bcd60e51b81526004016109a19060208082526004908201526319985a5b60e21b604082015260600190565b50565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015610b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b759190615413565b610b915760405162461bcd60e51b81526004016109a190615430565b6109b58360028484612f82565b6000546001600160a01b03163314610be55760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b60448201526064016109a1565b60008111610c265760405162461bcd60e51b815260206004820152600e60248201526d43414e4e4f545f42455f5a45524f60901b60448201526064016109a1565b60606001836003811115610c3c57610c3c614f3b565b03610c73575060408051808201909152601081526f36b0bc2a3930b232b9a832b92830b4b960811b60208201526005829055610dee565b6002836003811115610c8757610c87614f3b565b03610d16576064610c9c620186a06032615469565b610ca69190615496565b821015610cef5760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b60448201526064016109a1565b506040805180820190915260068082526536b0bc29b62360d11b6020830152829055610dee565b6003836003811115610d2a57610d2a614f3b565b03610db857610d3d620186a06002615469565b821015610d865760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b60448201526064016109a1565b5060408051808201909152601081526f36b0bc29b0b734ba3ca83937b334ba2360811b60208201526007829055610dee565b60405162461bcd60e51b815260206004820152600b60248201526a155394d5541413d495115160aa1b60448201526064016109a1565b80604051610dfc91906154ce565b604051908190038120838252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab9060200160405180910390a2505050565b6001600160a01b0382166000908152601160209081526040808320848452825291829020805483518184028101840190945280845260609392830182828015610ead57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e8f575b505050505090505b92915050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa158015610f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f289190615413565b610f745760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c54726967676572732900000000000060448201526064016109a1565b6109b5338484613620565b60116020528260005260406000206020528160005260406000208181548110610fa757600080fd5b6000918252602090912001546001600160a01b0316925083915050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa15801561100d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110319190615413565b61107d5760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c54726967676572732900000000000060448201526064016109a1565b61108b6064620186a0615496565b8111156110d15760405162461bcd60e51b81526020600482015260146024820152734645455f4652414354494f4e5f544f4f5f42494760601b60448201526064016109a1565b6000838152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff16600581111561111057611110614f3b565b600581111561112157611121614f3b565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b86041615156060870152600160701b85049093166080860152600160b01b90930490921660a0909301929092526000878152600d90915220549091506111b85760405162461bcd60e51b81526004016109a1906154ea565b6000848152600c6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1694830194909452600160b01b900463ffffffff1693810193909352600190810154909116606083015284600281111561122757611227614f3b565b036112895760018260200151600581111561124457611244614f3b565b146112845760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa6a0a925a2aa2fa7a92222a960811b60448201526064016109a1565b611334565b600284600281111561129d5761129d614f3b565b036112f9576002826020015160058111156112ba576112ba614f3b565b146112845760405162461bcd60e51b815260206004820152600f60248201526e2727aa2fa624a6a4aa2fa7a92222a960891b60448201526064016109a1565b60405162461bcd60e51b815260206004820152601060248201526f57524f4e475f4f524445525f5459504560801b60448201526064016109a1565b61135885826000015183606001518460200151866000015187606001518933613731565b5050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156113a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113cc9190615413565b6113e85760405162461bcd60e51b81526004016109a190615430565b6000848152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff16600581111561142757611427614f3b565b600581111561143857611438614f3b565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a09091015280519091506114b85760405162461bcd60e51b81526004016109a1906154ea565b6000858152600e60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b9091049091166060820152908080600288600381111561152757611527614f3b565b0361158a5784608001516115545783606001516001600160401b0316866001600160401b0316101561156f565b83606001516001600160401b0316866001600160401b031611155b925083606001516001600160401b031691506002905061166f565b600188600381111561159e5761159e614f3b565b036116015784608001516115cb5783604001516001600160401b0316866001600160401b031611156115e6565b83604001516001600160401b0316866001600160401b031610155b925083604001516001600160401b031691506001905061166f565b600388600381111561161557611615614f3b565b03611631575060019150506001600160401b038416600361166f565b60405162461bcd60e51b81526020600482015260136024820152722ba927a723afa624a6a4aa2faa2924a3a3a2a960691b60448201526064016109a1565b826116ac5760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b60448201526064016109a1565b60008060006116bc8c86866137fc565b9194509250905060038460048111156116d7576116d7614f3b565b036117445787608001516116f75780896001600160401b03161015611705565b80896001600160401b031611155b9550856117445760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b60448201526064016109a1565b8a600381111561175657611756614f3b565b604080516001600160401b038c16815260208101849052908101859052606081018490528d907fe67823c5c7b61d690bab4b46031d192b68f898b47bdf7daffbddff8e24aaf9bd9060800160405180910390a3505050505050505050505050565b6000546001600160a01b031633146117fe5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b60448201526064016109a1565b600082815260086020526040808220805460ff19168415159081179091559051909184917f996384f9c771a575699aadc5e543fb849613b350a1b29584a1ecca98d2cfc1709190a35050565b6118586064620186a0615496565b81565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c89190615413565b6118e45760405162461bcd60e51b81526004016109a190615514565b6000858152600d602052604090206002600182015460ff16600581111561190d5761190d614f3b565b1461192a5760405162461bcd60e51b81526004016109a19061553c565b6000868152600c6020908152604080832054600160a01b900461ffff168352600890915290205460ff16156119715760405162461bcd60e51b81526004016109a190615561565b6119b381600101600d9054906101000a900460ff16866001600160401b0316866001600160401b0316866001600160401b0316866001600160401b03166139fc565b60018101805468ffffffffffffffff001916610100426001600160401b0390811691909102919091179091556000878152600e6020908152604080832080546001600160801b0316600160801b8987169081026001600160c01b031691909117600160c01b898816908102919091178355600f85529483902080548c88166001600160801b03199091168117600160401b988d169889021782558451928352948201959095529182019290925260608101939093529188907f098a3c0f7acdf2c147440d705e162d395db886273731a238b250793cde346d859060800160405180910390a25050505050505050565b6004546001600160a01b03163314611ae85760405162461bcd60e51b815260206004820152600960248201526821526567697374727960b81b60448201526064016109a1565b6001600160a01b038381166000908152600a60205260409020541615611b505760405162461bcd60e51b815260206004820152601760248201527f41535345545f414c52454144595f535550504f5254454400000000000000000060448201526064016109a1565b6001600160a01b038084166000818152600a6020908152604080832080548689166001600160a01b03199182168117909255600b9093528184208054968816969093168617909255519092917fe34fb4592f12d191480ae66f1051ba82ee53c518b07f632579da8d40a74c77c891a4505050565b60408051606095861b6bffffffffffffffffffffffff199081166020808401919091529590961b909516603486015260f09290921b6001600160f01b031916604885015260e01b6001600160e01b031916604a8401528051602e818503018152604e9093019052815191012090565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca09190615413565b611cbc5760405162461bcd60e51b81526004016109a190615430565b6000848152600d60209081526040808320600e8352818420600c845293829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1696830196909652600160b01b900463ffffffff16938101939093526001015490921660608201528154919291611d465760405162461bcd60e51b81526004016109a1906154ea565b6003600184015460ff166005811115611d6157611d61614f3b565b14611d7e5760405162461bcd60e51b81526004016109a19061553c565b80516001600160a01b039081166000908152600b602052604081205490911690806001896002811115611db357611db3614f3b565b0361206e576000611e54846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f91906153fa565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16613ade565b9050886001600160401b0316816001600160401b031614611ea95760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b60448201526064016109a1565b85546001600160401b03600160801b909104811690821603611ef75760405162461bcd60e51b8152602060048201526007602482015266053414d455f54560cc1b60448201526064016109a1565b8092508560000160189054906101000a90046001600160401b03169150428660000160006101000a8154816001600160401b0302191690836001600160401b03160217905550836001600160a01b0316633cdc20f88c876060015188602001518b600001548c60010160099054906101000a900463ffffffff168d600101600d9054906101000a900460ff168e600101600e9054906101000a90046001600160401b03168e60000160109054906101000a90046001600160401b03168c6040518a63ffffffff1660e01b8152600401612036999897969594939291909889526001600160a01b0397909716602089015261ffff959095166040880152606087019390935263ffffffff919091166080860152151560a08501526001600160401b0390811660c085015290811660e0840152166101008201526101200190565b600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050506121ff565b600289600281111561208257612082614f3b565b03610db8576000612123846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee91906153fa565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16613bb0565b9050886001600160401b0316816001600160401b0316146121785760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b60448201526064016109a1565b85546001600160401b03600160c01b9091048116908216036121c65760405162461bcd60e51b815260206004820152600760248201526614d0535157d4d360ca1b60448201526064016109a1565b8554426001600160401b03908116600160401b026fffffffffffffffff0000000000000000198316178855600160801b90910416925090505b60018601546000906001600160401b03808a16600160701b909204161161223a576001870154600160701b90046001600160401b031661223c565b875b60018801546001600160401b0391821692506000918a8116600160701b909204161061227c576001880154600160701b90046001600160401b031661227e565b885b6001600160401b031690506122b988600101600d9054906101000a900460ff168383876001600160401b0316876001600160401b03166139fc565b86546001600160401b03858116600160801b0267ffffffffffffffff60801b19918616600160c01b02919091166001600160801b03909216919091171787558a600281111561230a5761230a614f3b565b866020015161ffff168d7f90bbb7e2b715065bd66ba75a34fca9b65694d5e75327dd0873a5e3e6883776678b600101600d9054906101000a900460ff168e60405161236a92919091151582526001600160401b0316602082015260400190565b60405180910390a4505050505050505050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156123c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ed9190615413565b6124095760405162461bcd60e51b81526004016109a190615430565b6000838152600f6020908152604091829020825160808101845290546001600160401b038082168352600160401b82048116938301849052600160801b8204811694830194909452600160c01b9004909216606083015261247c5760405162461bcd60e51b81526004016109a1906154ea565b80516001600160401b03808416911611806124ac5750816001600160401b031681602001516001600160401b0316105b156124c2576124bd30856001613620565b61252b565b60008060006124dc87866001600160401b031660046137fc565b6040805182815260208101859052908101839052929550909350915087907f9912c2c8197504aea5a1b52b98eeae3f4aecabe190feebc292455c355d4297cb9060600160405180910390a25050505b50505050565b6004805460405163731aa5f960e01b815233928101929092526000916001600160a01b039091169063731aa5f990602401602060405180830381865afa15801561257f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a39190615413565b6125bf5760405162461bcd60e51b81526004016109a190615514565b6125e784604001516001600160a01b039081166000908152600a602052604090205416151590565b6126335760405162461bcd60e51b815260206004820152601e60248201527f4e4f4e5f535550504f525445445f534554544c454d454e545f4153534554000060448201526064016109a1565b60208085015161ffff1660009081526008909152604090205460ff161561266c5760405162461bcd60e51b81526004016109a190615561565b600185600281111561268057612680614f3b565b148061269d5750600285600281111561269b5761269b614f3b565b145b6126e25760405162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f4f524445525f5459504560501b60448201526064016109a1565b612727836000015184606001516001600160401b031685608001516001600160401b03168660a001516001600160401b03168760c001516001600160401b03166139fc565b6005546040808601516001600160a01b03908116600090815260126020908152838220895190931682529182528281208289015161ffff168252909152205463ffffffff16106127af5760405162461bcd60e51b815260206004820152601360248201527226a0ac2faa2920a222a9afa822a92fa820a4a960691b60448201526064016109a1565b600554846060015163ffffffff16111580156127d45750606084015163ffffffff1615155b6128105760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be929c888ab609b1b60448201526064016109a1565b61282c8460400151856000015186602001518760600151613c6d565b9050612845846040015185600001518560200151613d86565b61285c846040015185600001518660200151613ecb565b6000818152600d602052604090208054156128a35760405162461bcd60e51b8152602060048201526007602482015266125117d554d15160ca1b60448201526064016109a1565b600180820180548651604088015163ffffffff908116600160481b026cffffffff00000000000000000019921515600160681b0260ff60681b19928a16600160b01b02929092166cffffffff0000000000000000ff60681b199094169390931717161790556020850151825560009087600281111561292457612924614f3b565b14612930576002612933565b60015b9050808260010160006101000a81548160ff0219169083600581111561295b5761295b614f3b565b0217905550428260010160016101000a8154816001600160401b0302191690836001600160401b031602179055506000600e600085815260200190815260200160002090508560a001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508560c001518160000160186101000a8154816001600160401b0302191690836001600160401b031602179055506000600f6000868152602001908152602001600020905086606001518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555086608001518160000160086101000a8154816001600160401b0302191690836001600160401b031602179055508660e001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508661010001518160000160186101000a8154816001600160401b0302191690836001600160401b03160217905550847fb21f813c247f0b33a494a91f6ce2775e44bbfa407565c53b88b89d844994ebb3848a8a8a604051612afc9493929190615586565b60405180910390a250505050949350505050565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7d9190615413565b612b995760405162461bcd60e51b81526004016109a190615514565b6000838152600d602052604090208054612bc55760405162461bcd60e51b81526004016109a1906154ea565b6003600182015460ff166005811115612be057612be0614f3b565b14612bfd5760405162461bcd60e51b81526004016109a19061553c565b6001810180546001600160401b034281166101000268ffffffffffffffffff19909216919091176004179091556000858152600f60209081526040918290208054868516600160401b81026001600160801b03199092169589169586179190911782558351948552918401919091529186917fb7bb5d6820a30953d2858e9c448319c4cebbc70c347961e25f1adfff46566689910160405180910390a25050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0e9190615413565b612d2a5760405162461bcd60e51b81526004016109a190615430565b6109b58360018484612f82565b6040805160a081018252600080825260208083018290528284018290526060830182905260808301829052848252600d8152838220845160e0810190955280548552600181015493949293909183019060ff166005811115612d9b57612d9b614f3b565b6005811115612dac57612dac614f3b565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b8604161515606080880191909152600160701b86048516608080890191909152600160b01b909604831660a09788015287518a52878101519092168984015294860151831690880152938201511515868401526000968752600e909352942054600160801b90041692820192909252919050565b6001600160a01b038316600090815260096020526040812081846003811115612e8a57612e8a614f3b565b6003811115612e9b57612e9b614f3b565b8152602001908152602001600020549050600060096000866001600160a01b03166001600160a01b031681526020019081526020016000206000856003811115612ee757612ee7614f3b565b6003811115612ef857612ef8614f3b565b8152602081019190915260400160002055612f1d6001600160a01b0385168383613ffe565b816001600160a01b0316836003811115612f3957612f39614f3b565b856001600160a01b03167f0e80b333c403be7cb491b3ba7f29fe30014c594adbcbec04272291b2f72f6e6a84604051612f7491815260200190565b60405180910390a450505050565b6000848152600f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811683860152600160801b8204811683850152600160c01b909104166060820152878452600d8352818420825160e0810190935280548352600181015491949390919083019060ff16600581111561300b5761300b614f3b565b600581111561301c5761301c614f3b565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a090910152805190915061309c5760405162461bcd60e51b81526004016109a1906154ea565b6000868152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff16838701819052600160b01b90920463ffffffff1683860152600190930154909216606082015290845260089092529091205460ff16156131215760405162461bcd60e51b81526004016109a190615561565b85600581111561313357613133614f3b565b8260200151600581111561314957613149614f3b565b146131665760405162461bcd60e51b81526004016109a19061553c565b600186600581111561317a5761317a614f3b565b036132235782516001600160401b03808716911611806131af5750846001600160401b031683602001516001600160401b0316105b1561321e576040516001600160401b038616815287907f82c058420d58fdfcaa301ef645c860145096603267b7b7ac02831312ac2ab4479060200160405180910390a261321687826000015183606001518460200151866000015187606001518a30613731565b50505061252b565b6132a9565b600286600581111561323757613237614f3b565b03610db85782516001600160401b0380871691161180159061326f5750846001600160401b031683602001516001600160401b031610155b61321e5760405162461bcd60e51b815260206004820152600b60248201526a50524943455f52414e474560a81b60448201526064016109a1565b80516001600160a01b039081166000908152600b60205260408120546060850151608086015191909316926132e3918b9185918b8a61405d565b9050816001600160a01b03166352713f678a85606001518660200151886000015189606001518a6080015188604001518f6040518963ffffffff1660e01b81526004016133899897969594939291909788526001600160a01b0396909616602088015261ffff949094166040870152606086019290925263ffffffff166080850152151560a08401526001600160401b0390811660c08401521660e08201526101000190565b60408051808303816000875af19250505080156133c3575060408051601f3d908101601f191682019092526133c09181019061566a565b60015b6134cc576133cf61568e565b806308c379a00361340857506133e36156aa565b806133ee575061340a565b8060405162461bcd60e51b81526004016109a19190615733565b505b3d808015613434576040519150601f19603f3d011682016040523d82523d6000602084013e613439565b606091505b50632eb752bf60e21b61344b82615766565b6001600160e01b0319160361027f57602481015160448201516040518c907ff2c847d05971bf83dd347e0732c1ef893111318fb2540f5fe6f9783cb8d6ae5b90613498908590859061579d565b60405180910390a26134c48c8760000151886060015189602001518b600001518c606001518f30613731565b505050613615565b60008b8152600d602090815260408083206001810180546001600160401b038f16600160701b0267ffffffffffffffff60701b1990911617905589516010909352922055865161351d9084906157bb565b8155600180820180546001600160401b0342166101000268ffffffffffffffffff199091161760031790558651613560918e919061355b86886157bb565b6143e0565b85516001600160a01b038082166000908152600a602052604090205461358892911684614494565b60008c8152600f60205260408082209190915584810151606086015191518e927fdd0164525ce1bb6897fbd7000a7d93633016a05f498d94903ca1fcc7911cdf8192613609928f9290899089906001600160401b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60405180910390a25050505b505050505050505050565b6000828152600d602052604090205461364b5760405162461bcd60e51b81526004016109a1906154ea565b6000828152600f6020526040812055600181600181111561366e5761366e614f3b565b036112f95760046000838152600d602052604090206001015460ff16600581111561369b5761369b614f3b565b146136b85760405162461bcd60e51b81526004016109a19061553c565b6000828152600d6020908152604080832060010180546001600160401b0342166101000268ffffffffffffffffff19909116176003179055519182526001600160a01b0385169184917f2cb817145129b5c52a6dc17e0605285c54d9c258fbf0a21e78bfff4e00813333910160405180910390a3505050565b6000888152600d6020908152604080832083815560010180546001600160d01b0319169055600f90915281208190556137796137738663ffffffff87166144ae565b846144cd565b905061378889896003846143e0565b6137938888886144dd565b600061379f82876157bb565b90506137ac898983614494565b826001600160a01b03168a7f0732bc6c415e7a220efee5f866e1e91a1335745b97373898ffecfddbc708a3e7846040516137e891815260200190565b60405180910390a350505050505050505050565b6000838152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff1695830195909552600160b01b900463ffffffff1692810192909252600101549091166060820152819081908161386488612d37565b80519091506138855760405162461bcd60e51b81526004016109a1906154ea565b6000806000806138988c87878e8e61477c565b9350935093509350846000015183111561391a578451600090620186a06138bf82876157bb565b6138c99190615469565b6138d39190615496565b90506007548111156139185760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d41493d1925560921b60448201526064016109a1565b505b81975082985080965084600001518411156139775760405162461bcd60e51b815260206004820152601e60248201527f434c4f53455f4645455f4c41524745525f5448414e5f504f534954494f4e000060448201526064016109a1565b6139888c87600001516002876143e0565b61399f8660000151876060015188602001516144dd565b60008c8152600d6020908152604080832083815560010180546001600160d01b0319169055600e825280832083905560109091528120556060860151865186516139ed9291908c908861482e565b50505050505093509350939050565b82841115613a3e5760405162461bcd60e51b815260206004820152600f60248201526e4d494e5f4d41585f5245564552534560881b60448201526064016109a1565b811580613a57575084613a5357838210613a57565b8282115b613a8e5760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b60448201526064016109a1565b801580613aa7575084613aa357828111613aa7565b8381105b6113585760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b60448201526064016109a1565b60006001600160401b0383161580613b0857508560070b613b028787868689614997565b60070b12155b15613ba4576000620186a0856001600160401b03166064896001600160401b0316896001600160401b0316613b3d9190615469565b613b479190615469565b613b519190615496565b613b5b9190615496565b905082613b9257856001600160401b0316816001600160401b03161115613b83576000613b9c565b613b8d81876157ce565b613b9c565b613b9c81876157f5565b915050613ba7565b50815b95945050505050565b60006001600160401b0383161580613be55750600654613bd290600019615815565b613bdf8787868689614997565b60070b13155b15613ba4576000620186a0856001600160401b03166064600654896001600160401b0316613c139190615469565b613c1d9190615469565b613c279190615496565b613c319190615496565b905082613c4257613b8d81876157f5565b856001600160401b0316816001600160401b03161115613c63576000613b9c565b613b9c81876157ce565b6000613c7b85858585611bc4565b6000818152600c60205260408120805492935091600160b01b900463ffffffff169003613d7d5780546001820180546001600160a01b038881166001600160a01b0319929092169190911790915563ffffffff8516600160b01b0263ffffffff60b01b1961ffff8816600160a01b026001600160b01b0319909416928a1692909217929092171617815560405182907f487ea6416487448c3ce943d750c8f67a275e4d8f26ac4093803bf63354b7006f90613d7490849081546001600160a01b03808216835260a082901c61ffff16602084015260b09190911c63ffffffff166040830152600190920154909116606082015260800190565b60405180910390a25b50949350505050565b80156109b5576040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015613dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613df791906153fa565b9050613e0e6001600160a01b038516843085614a23565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613e55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7991906153fa565b905082613e8683836157bb565b146113585760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b60448201526064016109a1565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052908120805463ffffffff1691613f1083615845565b82546101009290920a63ffffffff8181021990931691831602179091556001600160a01b038581166000908152601260209081526040808320938816835292815282822061ffff87168352905220541660010390506109b5576001600160a01b03808416600081815260116020908152604080832061ffff87168085529083528184208054600181018255818652848620018054978a166001600160a01b031990981688179055549484526012835281842095845294825280832094835293905291909120805463ffffffff9092166401000000000267ffffffff0000000019909216919091179055505050565b6040516001600160a01b038381166024830152604482018390526109b591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614a5c565b6040805160808101825260008082526020820181905291810182905260608101919091526000866001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156140c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140e591906153fa565b6000898152600e6020908152604091829020825160808101845290546001600160401b038082168352600160401b8204811693830193909352600160801b81048316938201849052600160c01b9004909116606082015293509091501580614158575060408301516001600160401b0316155b6141a45760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f54505f444546494e4954494f4e5300000000000000000060448201526064016109a1565b60608201516001600160401b031615806141c9575060608301516001600160401b0316155b6142155760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f534c5f444546494e4954494f4e5300000000000000000060448201526064016109a1565b60408301516001600160401b03161561428f57600061423f8585604001518963ffffffff16614abf565b90508561427557846001600160401b0316816001600160401b03161061426657600061427f565b61427081866157ce565b61427f565b61427f81866157f5565b6001600160401b03166040840152505b60608301516001600160401b0316156143095760006142b98585606001518963ffffffff16614abf565b9050856142cf576142ca81866157f5565b6142f9565b846001600160401b0316816001600160401b0316106142ef5760006142f9565b6142f981866157ce565b6001600160401b03166060840152505b61432081858863ffffffff16856040015189613ade565b6001600160401b03908116604084015242168252606082015161434f908290869063ffffffff8a169089613bb0565b6001600160401b0390811660608401908152428216602080860191825260009b8c52600e905260409a8b90208551815492519c87015193518516600160c01b026001600160c01b03948616600160801b02949094166001600160801b039d8616600160401b026001600160801b03199094169190951617919091179a909a1691909117179097559695505050505050565b801561252b576001600160a01b0383166000908152600960205260408120829184600381111561441257614412614f3b565b600381111561442357614423614f3b565b815260200190815260200160002060008282546144409190615868565b90915550829050600381111561445857614458614f3b565b836001600160a01b0316857f52aab89a61b38ba21feecda2012e9c20aec817e5d709d0633c3fd693bb949cbb84604051612f7491815260200190565b80156109b5576109b56001600160a01b0384168383613ffe565b600060646144bc8385615469565b6144c69190615496565b9392505050565b6000620186a06144bc8385615469565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052205463ffffffff16600103614713576001600160a01b038316600090815260116020908152604080832061ffff85168452909152902080546001101561469a576001600160a01b038481166000908152601260209081526040808320938716835292815282822061ffff8616835290522054815464010000000090910463ffffffff1690829061459f906001906157bb565b815481106145af576145af61587b565b6000918252602090912001546001600160a01b0316826145d0600184615891565b63ffffffff16815481106145e6576145e661587b565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918716815260129091526040812082918461462a600185615891565b63ffffffff16815481106146405761464061587b565b60009182526020808320909101546001600160a01b03168352828101939093526040918201812061ffff881682529092529020805463ffffffff929092166401000000000267ffffffff0000000019909216919091179055505b6001600160a01b038085166000908152601260209081526040808320938716835292815282822061ffff86168352905220805467ffffffffffffffff1916905580548190806146eb576146eb6158ae565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052908120805463ffffffff1691614758836158c4565b91906101000a81548163ffffffff021916908363ffffffff16021790555050505050565b83516001600160a01b039081166000908152600b60209081526040808320546060890151928901519151630f1a62d160e31b8152939485948594859493909216926378d31688926147d8928e92908d908d908d906004016158e4565b6080604051808303816000875af11580156147f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481b919061593b565b929c919b50995090975095505050505050565b6001600160a01b038085166000908152600a6020526040812054909116908385106148d75761485d83856157bb565b9050600061486b82876157bb565b6040516321d4911360e01b81526001600160a01b038a8116600483015260248201839052919250908416906321d4911390604401600060405180830381600087803b1580156148b957600080fd5b505af11580156148cd573d6000803e3d6000fd5b5050505050614983565b508360006148e582866157bb565b9050838111156149085761490387846148fe87856157bb565b614494565b614981565b6001600160a01b0383166321d491133061492284886157bb565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561496857600080fd5b505af115801561497c573d6000803e3d6000fd5b505050505b505b61498e868883614494565b50505050505050565b60008581846149af576149aa8688615971565b6149b9565b6149b98787615971565b905060008460070b620186a08360070b6149d39190615815565b6149dd9190615815565b90506000600789900b6149f16064846159a0565b6149fb91906159a0565b90508094508360070b8560070b13614a135784614a15565b835b9a9950505050505050505050565b6040516001600160a01b03848116602483015283811660448301526064820183905261252b9186918216906323b872dd9060840161402b565b6000614a716001600160a01b03841683614b0e565b90508051600014158015614a96575080806020019051810190614a949190615413565b155b156109b557604051635274afe760e01b81526001600160a01b03841660048201526024016109a1565b600080826001600160401b0316620186a06064866001600160401b0316886001600160401b0316614af09190615469565b614afa9190615469565b614b049190615496565b613ba79190615496565b60606144c68383600084600080856001600160a01b03168486604051614b3491906154ce565b60006040518083038185875af1925050503d8060008114614b71576040519150601f19603f3d011682016040523d82523d6000602084013e614b76565b606091505b5091509150614b86868383614b90565b9695505050505050565b606082614ba557614ba082614bec565b6144c6565b8151158015614bbc57506001600160a01b0384163b155b15614be557604051639996b31560e01b81526001600160a01b03851660048201526024016109a1565b50806144c6565b805115614bfc5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0381168114610b0557600080fd5b600060208284031215614c3c57600080fd5b81356144c681614c15565b600060208284031215614c5957600080fd5b5035919050565b60048110610b0557600080fd5b600080600060608486031215614c8257600080fd5b8335614c8d81614c15565b92506020840135614c9d81614c60565b91506040840135614cad81614c15565b809150509250925092565b80356001600160401b0381168114614ccf57600080fd5b919050565b600080600060608486031215614ce957600080fd5b83359250614cf960208501614cb8565b9150604084013590509250925092565b60008060408385031215614d1c57600080fd5b8235614d2781614c60565b946020939093013593505050565b60008060408385031215614d4857600080fd5b8235614d5381614c15565b91506020830135614d6381614c60565b809150509250929050565b60008060408385031215614d8157600080fd5b8235614d2781614c15565b6020808252825182820181905260009190848201906040850190845b81811015614dcd5783516001600160a01b031683529284019291840191600101614da8565b50909695505050505050565b600080600060608486031215614dee57600080fd5b83359250602084013560028110614e0457600080fd5b929592945050506040919091013590565b600080600060608486031215614e2a57600080fd5b8335614e3581614c15565b95602085013595506040909401359392505050565b60038110610b0557600080fd5b600080600060608486031215614e6c57600080fd5b833592506020840135614e0481614e4a565b60008060008060808587031215614e9457600080fd5b843593506020850135614ea681614c60565b9250614eb460408601614cb8565b9150614ec260608601614cb8565b905092959194509250565b8015158114610b0557600080fd5b8035614ccf81614ecd565b60008060408385031215614ef957600080fd5b823591506020830135614d6381614ecd565b600080600060608486031215614f2057600080fd5b8335614f2b81614c15565b92506020840135614e0481614c15565b634e487b7160e01b600052602160045260246000fd5b60068110614f6157614f61614f3b565b9052565b87815260e08101614f796020830189614f51565b6001600160401b03968716604083015263ffffffff958616606083015293151560808201529190941660a08201529290911660c09092019190915292915050565b60a08101614fc88288614f51565b6001600160401b0395909516602082015261ffff939093166040840152901515606083015263ffffffff16608090910152919050565b600080600080600060a0868803121561501657600080fd5b8535945061502660208701614cb8565b935061503460408701614cb8565b925061504260608701614cb8565b915061505060808701614cb8565b90509295509295909350565b60008060006060848603121561507157600080fd5b833561507c81614c15565b92506020840135614c9d81614c15565b803561ffff81168114614ccf57600080fd5b803563ffffffff81168114614ccf57600080fd5b600080600080608085870312156150c857600080fd5b84356150d381614c15565b935060208501356150e381614c15565b92506150f16040860161508c565b9150614ec26060860161509e565b6000806000806080858703121561511557600080fd5b843593506020850135614ea681614e4a565b60008060006060848603121561513c57600080fd5b8335925061514c60208501614cb8565b915061515a60408501614cb8565b90509250925092565b601f8201601f191681016001600160401b038111828210171561519657634e487b7160e01b600052604160045260246000fd5b6040525050565b60405161012081016001600160401b03811182821017156151ce57634e487b7160e01b600052604160045260246000fd5b60405290565b600061012082840312156151e757600080fd5b6151ef61519d565b90506151fa82614edb565b8152602082013560208201526152126040830161509e565b604082015261522360608301614cb8565b606082015261523460808301614cb8565b608082015261524560a08301614cb8565b60a082015261525660c08301614cb8565b60c082015261526760e08301614cb8565b60e082015261010061527a818401614cb8565b9082015292915050565b6000806000808486036101e081121561529c57600080fd5b85356152a781614e4a565b94506080601f19820112156152bb57600080fd5b50604051608081018181106001600160401b03821117156152ec57634e487b7160e01b600052604160045260246000fd5b60405260208601356152fd81614c15565b815261530b6040870161508c565b6020820152606086013561531e81614c15565b604082015261532f6080870161509e565b606082015292506153438660a087016151d4565b9150614ec26101c0860161509e565b8051825263ffffffff602082015116602083015260408101511515604083015260608101516001600160401b03808216606085015280608084015116608085015250505050565b60a08101610eb58284615352565b606081016153b58286614f51565b6001600160401b039390931660208201526001600160a01b0391909116604090910152919050565b6000602082840312156153ef57600080fd5b81516144c681614c15565b60006020828403121561540c57600080fd5b5051919050565b60006020828403121561542557600080fd5b81516144c681614ecd565b60208082526009908201526821547269676765727360b81b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610eb557610eb5615453565b634e487b7160e01b600052601260045260246000fd5b6000826154a5576154a5615480565b500490565b60005b838110156154c55781810151838201526020016154ad565b50506000910152565b600082516154e08184602087016154aa565b9190910192915050565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b6020808252600e908201526d08551c9859195c9cd41bdc9d185b60921b604082015260600190565b6020808252600b908201526a57524f4e475f504841534560a81b604082015260600190565b6020808252600b908201526a1410525497d4105554d15160aa1b604082015260600190565b6101e081016155958287614f51565b60018060a01b0380865116602084015261ffff602087015116604084015280604087015116606084015250606085015163ffffffff80821660808501528551151560a0850152602086015160c08501528060408701511660e08501525050606084015161010061560f818501836001600160401b03169052565b60808601516001600160401b0390811661012086015260a0870151811661014086015260c0870151811661016086015260e0870151811661018086015290860151166101a08401525063ffffffff83166101c0830152613ba7565b6000806040838503121561567d57600080fd5b505080516020909101519092909150565b600060033d11156156a75760046000803e5060005160e01c5b90565b600060443d10156156b85790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156156e757505050505090565b82850191508151818111156156ff5750505050505090565b843d87010160208285010111156157195750505050505090565b61572860208286010187615163565b509095945050505050565b60208152600082518060208401526157528160408501602087016154aa565b601f01601f19169190910160400192915050565b805160208201516001600160e01b031980821692919060048310156157955780818460040360031b1b83161693505b505050919050565b60408101601284106157b1576157b1614f3b565b9281526020015290565b81810381811115610eb557610eb5615453565b6001600160401b038281168282160390808211156157ee576157ee615453565b5092915050565b6001600160401b038181168382160190808211156157ee576157ee615453565b80820260008212600160ff1b8414161561583157615831615453565b8181058314821517610eb557610eb5615453565b600063ffffffff80831681810361585e5761585e615453565b6001019392505050565b80820180821115610eb557610eb5615453565b634e487b7160e01b600052603260045260246000fd5b63ffffffff8281168282160390808211156157ee576157ee615453565b634e487b7160e01b600052603160045260246000fd5b600063ffffffff8216806158da576158da615453565b6000190192915050565b8681526001600160a01b038616602082015261ffff8516604082015261014081016159126060830186615352565b836101008301526005831061592957615929614f3b565b82610120830152979650505050505050565b6000806000806080858703121561595157600080fd5b505082516020840151604085015160609095015191969095509092509050565b600782810b9082900b03677fffffffffffffff198112677fffffffffffffff82131715610eb557610eb5615453565b6000826159af576159af615480565b600160ff1b8214600019841416156159c9576159c9615453565b50059056fea2646970667358221220dda688b0ed3677ee0cecc93216cfa1c23d52c51d3de4b5754befe318ad663cfc64736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061027f5760003560e01c80638c01936e1161015c578063c07f9921116100ce578063f2eb245e11610087578063f2eb245e1461081f578063f51f3fd31461083f578063f555f69714610848578063f65d9dbe14610868578063f851a44014610871578063f9b9484e1461088457600080fd5b8063c07f992114610778578063ca3a3a821461078b578063cae290c81461079e578063ddf474f1146107b1578063e640f33b146107f9578063eb4891401461080c57600080fd5b80639ff69ffa116101205780639ff69ffa1461071d578063a2a25ea614610730578063a40d726814610743578063aaf5eb6814610756578063ad1f2b5614610765578063b71f3cfe1461076d57600080fd5b80638c01936e146105915780638f7a8fb5146105f157806393a7f6a71461066c57806394a1e6e51461069a57806395be5050146106a257600080fd5b80635c60da1b116101f557806376d901be116101b957806376d901be146105125780637b1039991461054557806380193b261461055857806380a7f3d414610562578063825714091461057557806386dc49751461057e57600080fd5b80635c60da1b14610435578063652dcb431461044857806366307a4f1461045b5780636e01af8d146104d657806374d8b78e146104e957600080fd5b806324b22a1f1161024757806324b22a1f1461039057806326782247146103a357806330d073d0146103b657806331867212146103ef578063396f7b231461040f5780634ebe5c331461042257600080fd5b806303b90a8714610284578063042e37c5146102ca57806318fa4714146103555780631d504dc61461036a5780631ea9af6b1461037d575b600080fd5b6102ad610292366004614c2a565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103196102d8366004614c47565b600c60205260009081526040902080546001909101546001600160a01b0380831692600160a01b810461ffff1692600160b01b90910463ffffffff16911684565b604080516001600160a01b03958616815261ffff909416602085015263ffffffff909216918301919091529190911660608201526080016102c1565b610368610363366004614c6d565b6108e6565b005b610368610378366004614c2a565b6109ba565b61036861038b366004614cd4565b610b08565b61036861039e366004614d09565b610b9e565b6001546102ad906001600160a01b031681565b6103e16103c4366004614d35565b600960209081526000928352604080842090915290825290205481565b6040519081526020016102c1565b6104026103fd366004614d6e565b610e3b565b6040516102c19190614d8c565b6003546102ad906001600160a01b031681565b610368610430366004614dd9565b610ebb565b6002546102ad906001600160a01b031681565b6102ad610456366004614e15565b610f7f565b6104a3610469366004614c47565b600e602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b03958616815293851660208501529184169183019190915290911660608201526080016102c1565b6103686104e4366004614e57565b610fc4565b6102ad6104f7366004614c2a565b600a602052600090815260409020546001600160a01b031681565b610535610520366004614c47565b60086020526000908152604090205460ff1681565b60405190151581526020016102c1565b6004546102ad906001600160a01b031681565b6103e1620186a081565b610368610570366004614e7e565b61135f565b6103e160075481565b61036861058c366004614ee6565b6117b7565b6105d461059f366004614f0b565b601260209081526000938452604080852082529284528284209052825290205463ffffffff8082169164010000000090041682565b6040805163ffffffff9384168152929091166020830152016102c1565b6106596105ff366004614c47565b600d602052600090815260409020805460019091015460ff808216916001600160401b03610100820481169263ffffffff600160481b8404811693600160681b810490921692600160701b83041691600160b01b90041687565b6040516102c19796959493929190614f65565b61053561067a366004614c2a565b6001600160a01b039081166000908152600a602052604090205416151590565b6103e161184a565b61070c6106b0366004614c47565b6000908152600d6020818152604080842060010154600c835293205491905260ff8083169361010084046001600160401b031693600160a01b90930461ffff1692600160681b810490921691600160b01b900463ffffffff1690565b6040516102c1959493929190614fba565b61036861072b366004614ffe565b61185b565b61036861073e36600461505c565b611aa2565b6103e16107513660046150b2565b611bc4565b6103e1670de0b6b3a764000081565b6103e1606481565b6103e1633b9aca0081565b6103686107863660046150ff565b611c33565b610368610799366004615127565b612380565b6103e16107ac366004615284565b612531565b6104a36107bf366004614c47565b600f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b610368610807366004615127565b612b10565b61036861081a366004614cd4565b612ca1565b6103e161082d366004614c47565b60106020526000908152604090205481565b6103e160065481565b61085b610856366004614c47565b612d37565b6040516102c19190615399565b6103e160055481565b6000546102ad906001600160a01b031681565b6108d7610892366004614c47565b6000908152600d60209081526040808320600190810154600c90935292209091015460ff8216926101009092046001600160401b0316916001600160a01b0390911690565b6040516102c1939291906153a7565b6004805460405163a8e36e5b60e01b81526001600160a01b038681169382019390935291169063a8e36e5b90602401602060405180830381865afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095691906153dd565b6001600160a01b0316336001600160a01b0316146109aa5760405162461bcd60e51b815260206004820152600c60248201526b10a332b2b9a6b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6109b5838383612e5f565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1c91906153dd565b6001600160a01b0316336001600160a01b031614610a6b5760405162461bcd60e51b815260206004820152600c60248201526b10b83937bc3c9730b236b4b760a11b60448201526064016109a1565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acf91906153fa565b15610b055760405162461bcd60e51b81526004016109a19060208082526004908201526319985a5b60e21b604082015260600190565b50565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015610b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b759190615413565b610b915760405162461bcd60e51b81526004016109a190615430565b6109b58360028484612f82565b6000546001600160a01b03163314610be55760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b60448201526064016109a1565b60008111610c265760405162461bcd60e51b815260206004820152600e60248201526d43414e4e4f545f42455f5a45524f60901b60448201526064016109a1565b60606001836003811115610c3c57610c3c614f3b565b03610c73575060408051808201909152601081526f36b0bc2a3930b232b9a832b92830b4b960811b60208201526005829055610dee565b6002836003811115610c8757610c87614f3b565b03610d16576064610c9c620186a06032615469565b610ca69190615496565b821015610cef5760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b60448201526064016109a1565b506040805180820190915260068082526536b0bc29b62360d11b6020830152829055610dee565b6003836003811115610d2a57610d2a614f3b565b03610db857610d3d620186a06002615469565b821015610d865760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b60448201526064016109a1565b5060408051808201909152601081526f36b0bc29b0b734ba3ca83937b334ba2360811b60208201526007829055610dee565b60405162461bcd60e51b815260206004820152600b60248201526a155394d5541413d495115160aa1b60448201526064016109a1565b80604051610dfc91906154ce565b604051908190038120838252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab9060200160405180910390a2505050565b6001600160a01b0382166000908152601160209081526040808320848452825291829020805483518184028101840190945280845260609392830182828015610ead57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e8f575b505050505090505b92915050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa158015610f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f289190615413565b610f745760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c54726967676572732900000000000060448201526064016109a1565b6109b5338484613620565b60116020528260005260406000206020528160005260406000208181548110610fa757600080fd5b6000918252602090912001546001600160a01b0316925083915050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa15801561100d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110319190615413565b61107d5760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c54726967676572732900000000000060448201526064016109a1565b61108b6064620186a0615496565b8111156110d15760405162461bcd60e51b81526020600482015260146024820152734645455f4652414354494f4e5f544f4f5f42494760601b60448201526064016109a1565b6000838152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff16600581111561111057611110614f3b565b600581111561112157611121614f3b565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b86041615156060870152600160701b85049093166080860152600160b01b90930490921660a0909301929092526000878152600d90915220549091506111b85760405162461bcd60e51b81526004016109a1906154ea565b6000848152600c6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1694830194909452600160b01b900463ffffffff1693810193909352600190810154909116606083015284600281111561122757611227614f3b565b036112895760018260200151600581111561124457611244614f3b565b146112845760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa6a0a925a2aa2fa7a92222a960811b60448201526064016109a1565b611334565b600284600281111561129d5761129d614f3b565b036112f9576002826020015160058111156112ba576112ba614f3b565b146112845760405162461bcd60e51b815260206004820152600f60248201526e2727aa2fa624a6a4aa2fa7a92222a960891b60448201526064016109a1565b60405162461bcd60e51b815260206004820152601060248201526f57524f4e475f4f524445525f5459504560801b60448201526064016109a1565b61135885826000015183606001518460200151866000015187606001518933613731565b5050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156113a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113cc9190615413565b6113e85760405162461bcd60e51b81526004016109a190615430565b6000848152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff16600581111561142757611427614f3b565b600581111561143857611438614f3b565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a09091015280519091506114b85760405162461bcd60e51b81526004016109a1906154ea565b6000858152600e60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b9091049091166060820152908080600288600381111561152757611527614f3b565b0361158a5784608001516115545783606001516001600160401b0316866001600160401b0316101561156f565b83606001516001600160401b0316866001600160401b031611155b925083606001516001600160401b031691506002905061166f565b600188600381111561159e5761159e614f3b565b036116015784608001516115cb5783604001516001600160401b0316866001600160401b031611156115e6565b83604001516001600160401b0316866001600160401b031610155b925083604001516001600160401b031691506001905061166f565b600388600381111561161557611615614f3b565b03611631575060019150506001600160401b038416600361166f565b60405162461bcd60e51b81526020600482015260136024820152722ba927a723afa624a6a4aa2faa2924a3a3a2a960691b60448201526064016109a1565b826116ac5760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b60448201526064016109a1565b60008060006116bc8c86866137fc565b9194509250905060038460048111156116d7576116d7614f3b565b036117445787608001516116f75780896001600160401b03161015611705565b80896001600160401b031611155b9550856117445760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b60448201526064016109a1565b8a600381111561175657611756614f3b565b604080516001600160401b038c16815260208101849052908101859052606081018490528d907fe67823c5c7b61d690bab4b46031d192b68f898b47bdf7daffbddff8e24aaf9bd9060800160405180910390a3505050505050505050505050565b6000546001600160a01b031633146117fe5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b60448201526064016109a1565b600082815260086020526040808220805460ff19168415159081179091559051909184917f996384f9c771a575699aadc5e543fb849613b350a1b29584a1ecca98d2cfc1709190a35050565b6118586064620186a0615496565b81565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c89190615413565b6118e45760405162461bcd60e51b81526004016109a190615514565b6000858152600d602052604090206002600182015460ff16600581111561190d5761190d614f3b565b1461192a5760405162461bcd60e51b81526004016109a19061553c565b6000868152600c6020908152604080832054600160a01b900461ffff168352600890915290205460ff16156119715760405162461bcd60e51b81526004016109a190615561565b6119b381600101600d9054906101000a900460ff16866001600160401b0316866001600160401b0316866001600160401b0316866001600160401b03166139fc565b60018101805468ffffffffffffffff001916610100426001600160401b0390811691909102919091179091556000878152600e6020908152604080832080546001600160801b0316600160801b8987169081026001600160c01b031691909117600160c01b898816908102919091178355600f85529483902080548c88166001600160801b03199091168117600160401b988d169889021782558451928352948201959095529182019290925260608101939093529188907f098a3c0f7acdf2c147440d705e162d395db886273731a238b250793cde346d859060800160405180910390a25050505050505050565b6004546001600160a01b03163314611ae85760405162461bcd60e51b815260206004820152600960248201526821526567697374727960b81b60448201526064016109a1565b6001600160a01b038381166000908152600a60205260409020541615611b505760405162461bcd60e51b815260206004820152601760248201527f41535345545f414c52454144595f535550504f5254454400000000000000000060448201526064016109a1565b6001600160a01b038084166000818152600a6020908152604080832080548689166001600160a01b03199182168117909255600b9093528184208054968816969093168617909255519092917fe34fb4592f12d191480ae66f1051ba82ee53c518b07f632579da8d40a74c77c891a4505050565b60408051606095861b6bffffffffffffffffffffffff199081166020808401919091529590961b909516603486015260f09290921b6001600160f01b031916604885015260e01b6001600160e01b031916604a8401528051602e818503018152604e9093019052815191012090565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca09190615413565b611cbc5760405162461bcd60e51b81526004016109a190615430565b6000848152600d60209081526040808320600e8352818420600c845293829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1696830196909652600160b01b900463ffffffff16938101939093526001015490921660608201528154919291611d465760405162461bcd60e51b81526004016109a1906154ea565b6003600184015460ff166005811115611d6157611d61614f3b565b14611d7e5760405162461bcd60e51b81526004016109a19061553c565b80516001600160a01b039081166000908152600b602052604081205490911690806001896002811115611db357611db3614f3b565b0361206e576000611e54846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f91906153fa565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16613ade565b9050886001600160401b0316816001600160401b031614611ea95760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b60448201526064016109a1565b85546001600160401b03600160801b909104811690821603611ef75760405162461bcd60e51b8152602060048201526007602482015266053414d455f54560cc1b60448201526064016109a1565b8092508560000160189054906101000a90046001600160401b03169150428660000160006101000a8154816001600160401b0302191690836001600160401b03160217905550836001600160a01b0316633cdc20f88c876060015188602001518b600001548c60010160099054906101000a900463ffffffff168d600101600d9054906101000a900460ff168e600101600e9054906101000a90046001600160401b03168e60000160109054906101000a90046001600160401b03168c6040518a63ffffffff1660e01b8152600401612036999897969594939291909889526001600160a01b0397909716602089015261ffff959095166040880152606087019390935263ffffffff919091166080860152151560a08501526001600160401b0390811660c085015290811660e0840152166101008201526101200190565b600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050506121ff565b600289600281111561208257612082614f3b565b03610db8576000612123846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee91906153fa565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16613bb0565b9050886001600160401b0316816001600160401b0316146121785760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b60448201526064016109a1565b85546001600160401b03600160c01b9091048116908216036121c65760405162461bcd60e51b815260206004820152600760248201526614d0535157d4d360ca1b60448201526064016109a1565b8554426001600160401b03908116600160401b026fffffffffffffffff0000000000000000198316178855600160801b90910416925090505b60018601546000906001600160401b03808a16600160701b909204161161223a576001870154600160701b90046001600160401b031661223c565b875b60018801546001600160401b0391821692506000918a8116600160701b909204161061227c576001880154600160701b90046001600160401b031661227e565b885b6001600160401b031690506122b988600101600d9054906101000a900460ff168383876001600160401b0316876001600160401b03166139fc565b86546001600160401b03858116600160801b0267ffffffffffffffff60801b19918616600160c01b02919091166001600160801b03909216919091171787558a600281111561230a5761230a614f3b565b866020015161ffff168d7f90bbb7e2b715065bd66ba75a34fca9b65694d5e75327dd0873a5e3e6883776678b600101600d9054906101000a900460ff168e60405161236a92919091151582526001600160401b0316602082015260400190565b60405180910390a4505050505050505050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156123c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ed9190615413565b6124095760405162461bcd60e51b81526004016109a190615430565b6000838152600f6020908152604091829020825160808101845290546001600160401b038082168352600160401b82048116938301849052600160801b8204811694830194909452600160c01b9004909216606083015261247c5760405162461bcd60e51b81526004016109a1906154ea565b80516001600160401b03808416911611806124ac5750816001600160401b031681602001516001600160401b0316105b156124c2576124bd30856001613620565b61252b565b60008060006124dc87866001600160401b031660046137fc565b6040805182815260208101859052908101839052929550909350915087907f9912c2c8197504aea5a1b52b98eeae3f4aecabe190feebc292455c355d4297cb9060600160405180910390a25050505b50505050565b6004805460405163731aa5f960e01b815233928101929092526000916001600160a01b039091169063731aa5f990602401602060405180830381865afa15801561257f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a39190615413565b6125bf5760405162461bcd60e51b81526004016109a190615514565b6125e784604001516001600160a01b039081166000908152600a602052604090205416151590565b6126335760405162461bcd60e51b815260206004820152601e60248201527f4e4f4e5f535550504f525445445f534554544c454d454e545f4153534554000060448201526064016109a1565b60208085015161ffff1660009081526008909152604090205460ff161561266c5760405162461bcd60e51b81526004016109a190615561565b600185600281111561268057612680614f3b565b148061269d5750600285600281111561269b5761269b614f3b565b145b6126e25760405162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f4f524445525f5459504560501b60448201526064016109a1565b612727836000015184606001516001600160401b031685608001516001600160401b03168660a001516001600160401b03168760c001516001600160401b03166139fc565b6005546040808601516001600160a01b03908116600090815260126020908152838220895190931682529182528281208289015161ffff168252909152205463ffffffff16106127af5760405162461bcd60e51b815260206004820152601360248201527226a0ac2faa2920a222a9afa822a92fa820a4a960691b60448201526064016109a1565b600554846060015163ffffffff16111580156127d45750606084015163ffffffff1615155b6128105760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be929c888ab609b1b60448201526064016109a1565b61282c8460400151856000015186602001518760600151613c6d565b9050612845846040015185600001518560200151613d86565b61285c846040015185600001518660200151613ecb565b6000818152600d602052604090208054156128a35760405162461bcd60e51b8152602060048201526007602482015266125117d554d15160ca1b60448201526064016109a1565b600180820180548651604088015163ffffffff908116600160481b026cffffffff00000000000000000019921515600160681b0260ff60681b19928a16600160b01b02929092166cffffffff0000000000000000ff60681b199094169390931717161790556020850151825560009087600281111561292457612924614f3b565b14612930576002612933565b60015b9050808260010160006101000a81548160ff0219169083600581111561295b5761295b614f3b565b0217905550428260010160016101000a8154816001600160401b0302191690836001600160401b031602179055506000600e600085815260200190815260200160002090508560a001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508560c001518160000160186101000a8154816001600160401b0302191690836001600160401b031602179055506000600f6000868152602001908152602001600020905086606001518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555086608001518160000160086101000a8154816001600160401b0302191690836001600160401b031602179055508660e001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508661010001518160000160186101000a8154816001600160401b0302191690836001600160401b03160217905550847fb21f813c247f0b33a494a91f6ce2775e44bbfa407565c53b88b89d844994ebb3848a8a8a604051612afc9493929190615586565b60405180910390a250505050949350505050565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7d9190615413565b612b995760405162461bcd60e51b81526004016109a190615514565b6000838152600d602052604090208054612bc55760405162461bcd60e51b81526004016109a1906154ea565b6003600182015460ff166005811115612be057612be0614f3b565b14612bfd5760405162461bcd60e51b81526004016109a19061553c565b6001810180546001600160401b034281166101000268ffffffffffffffffff19909216919091176004179091556000858152600f60209081526040918290208054868516600160401b81026001600160801b03199092169589169586179190911782558351948552918401919091529186917fb7bb5d6820a30953d2858e9c448319c4cebbc70c347961e25f1adfff46566689910160405180910390a25050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0e9190615413565b612d2a5760405162461bcd60e51b81526004016109a190615430565b6109b58360018484612f82565b6040805160a081018252600080825260208083018290528284018290526060830182905260808301829052848252600d8152838220845160e0810190955280548552600181015493949293909183019060ff166005811115612d9b57612d9b614f3b565b6005811115612dac57612dac614f3b565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b8604161515606080880191909152600160701b86048516608080890191909152600160b01b909604831660a09788015287518a52878101519092168984015294860151831690880152938201511515868401526000968752600e909352942054600160801b90041692820192909252919050565b6001600160a01b038316600090815260096020526040812081846003811115612e8a57612e8a614f3b565b6003811115612e9b57612e9b614f3b565b8152602001908152602001600020549050600060096000866001600160a01b03166001600160a01b031681526020019081526020016000206000856003811115612ee757612ee7614f3b565b6003811115612ef857612ef8614f3b565b8152602081019190915260400160002055612f1d6001600160a01b0385168383613ffe565b816001600160a01b0316836003811115612f3957612f39614f3b565b856001600160a01b03167f0e80b333c403be7cb491b3ba7f29fe30014c594adbcbec04272291b2f72f6e6a84604051612f7491815260200190565b60405180910390a450505050565b6000848152600f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811683860152600160801b8204811683850152600160c01b909104166060820152878452600d8352818420825160e0810190935280548352600181015491949390919083019060ff16600581111561300b5761300b614f3b565b600581111561301c5761301c614f3b565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a090910152805190915061309c5760405162461bcd60e51b81526004016109a1906154ea565b6000868152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff16838701819052600160b01b90920463ffffffff1683860152600190930154909216606082015290845260089092529091205460ff16156131215760405162461bcd60e51b81526004016109a190615561565b85600581111561313357613133614f3b565b8260200151600581111561314957613149614f3b565b146131665760405162461bcd60e51b81526004016109a19061553c565b600186600581111561317a5761317a614f3b565b036132235782516001600160401b03808716911611806131af5750846001600160401b031683602001516001600160401b0316105b1561321e576040516001600160401b038616815287907f82c058420d58fdfcaa301ef645c860145096603267b7b7ac02831312ac2ab4479060200160405180910390a261321687826000015183606001518460200151866000015187606001518a30613731565b50505061252b565b6132a9565b600286600581111561323757613237614f3b565b03610db85782516001600160401b0380871691161180159061326f5750846001600160401b031683602001516001600160401b031610155b61321e5760405162461bcd60e51b815260206004820152600b60248201526a50524943455f52414e474560a81b60448201526064016109a1565b80516001600160a01b039081166000908152600b60205260408120546060850151608086015191909316926132e3918b9185918b8a61405d565b9050816001600160a01b03166352713f678a85606001518660200151886000015189606001518a6080015188604001518f6040518963ffffffff1660e01b81526004016133899897969594939291909788526001600160a01b0396909616602088015261ffff949094166040870152606086019290925263ffffffff166080850152151560a08401526001600160401b0390811660c08401521660e08201526101000190565b60408051808303816000875af19250505080156133c3575060408051601f3d908101601f191682019092526133c09181019061566a565b60015b6134cc576133cf61568e565b806308c379a00361340857506133e36156aa565b806133ee575061340a565b8060405162461bcd60e51b81526004016109a19190615733565b505b3d808015613434576040519150601f19603f3d011682016040523d82523d6000602084013e613439565b606091505b50632eb752bf60e21b61344b82615766565b6001600160e01b0319160361027f57602481015160448201516040518c907ff2c847d05971bf83dd347e0732c1ef893111318fb2540f5fe6f9783cb8d6ae5b90613498908590859061579d565b60405180910390a26134c48c8760000151886060015189602001518b600001518c606001518f30613731565b505050613615565b60008b8152600d602090815260408083206001810180546001600160401b038f16600160701b0267ffffffffffffffff60701b1990911617905589516010909352922055865161351d9084906157bb565b8155600180820180546001600160401b0342166101000268ffffffffffffffffff199091161760031790558651613560918e919061355b86886157bb565b6143e0565b85516001600160a01b038082166000908152600a602052604090205461358892911684614494565b60008c8152600f60205260408082209190915584810151606086015191518e927fdd0164525ce1bb6897fbd7000a7d93633016a05f498d94903ca1fcc7911cdf8192613609928f9290899089906001600160401b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60405180910390a25050505b505050505050505050565b6000828152600d602052604090205461364b5760405162461bcd60e51b81526004016109a1906154ea565b6000828152600f6020526040812055600181600181111561366e5761366e614f3b565b036112f95760046000838152600d602052604090206001015460ff16600581111561369b5761369b614f3b565b146136b85760405162461bcd60e51b81526004016109a19061553c565b6000828152600d6020908152604080832060010180546001600160401b0342166101000268ffffffffffffffffff19909116176003179055519182526001600160a01b0385169184917f2cb817145129b5c52a6dc17e0605285c54d9c258fbf0a21e78bfff4e00813333910160405180910390a3505050565b6000888152600d6020908152604080832083815560010180546001600160d01b0319169055600f90915281208190556137796137738663ffffffff87166144ae565b846144cd565b905061378889896003846143e0565b6137938888886144dd565b600061379f82876157bb565b90506137ac898983614494565b826001600160a01b03168a7f0732bc6c415e7a220efee5f866e1e91a1335745b97373898ffecfddbc708a3e7846040516137e891815260200190565b60405180910390a350505050505050505050565b6000838152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff1695830195909552600160b01b900463ffffffff1692810192909252600101549091166060820152819081908161386488612d37565b80519091506138855760405162461bcd60e51b81526004016109a1906154ea565b6000806000806138988c87878e8e61477c565b9350935093509350846000015183111561391a578451600090620186a06138bf82876157bb565b6138c99190615469565b6138d39190615496565b90506007548111156139185760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d41493d1925560921b60448201526064016109a1565b505b81975082985080965084600001518411156139775760405162461bcd60e51b815260206004820152601e60248201527f434c4f53455f4645455f4c41524745525f5448414e5f504f534954494f4e000060448201526064016109a1565b6139888c87600001516002876143e0565b61399f8660000151876060015188602001516144dd565b60008c8152600d6020908152604080832083815560010180546001600160d01b0319169055600e825280832083905560109091528120556060860151865186516139ed9291908c908861482e565b50505050505093509350939050565b82841115613a3e5760405162461bcd60e51b815260206004820152600f60248201526e4d494e5f4d41585f5245564552534560881b60448201526064016109a1565b811580613a57575084613a5357838210613a57565b8282115b613a8e5760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b60448201526064016109a1565b801580613aa7575084613aa357828111613aa7565b8381105b6113585760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b60448201526064016109a1565b60006001600160401b0383161580613b0857508560070b613b028787868689614997565b60070b12155b15613ba4576000620186a0856001600160401b03166064896001600160401b0316896001600160401b0316613b3d9190615469565b613b479190615469565b613b519190615496565b613b5b9190615496565b905082613b9257856001600160401b0316816001600160401b03161115613b83576000613b9c565b613b8d81876157ce565b613b9c565b613b9c81876157f5565b915050613ba7565b50815b95945050505050565b60006001600160401b0383161580613be55750600654613bd290600019615815565b613bdf8787868689614997565b60070b13155b15613ba4576000620186a0856001600160401b03166064600654896001600160401b0316613c139190615469565b613c1d9190615469565b613c279190615496565b613c319190615496565b905082613c4257613b8d81876157f5565b856001600160401b0316816001600160401b03161115613c63576000613b9c565b613b9c81876157ce565b6000613c7b85858585611bc4565b6000818152600c60205260408120805492935091600160b01b900463ffffffff169003613d7d5780546001820180546001600160a01b038881166001600160a01b0319929092169190911790915563ffffffff8516600160b01b0263ffffffff60b01b1961ffff8816600160a01b026001600160b01b0319909416928a1692909217929092171617815560405182907f487ea6416487448c3ce943d750c8f67a275e4d8f26ac4093803bf63354b7006f90613d7490849081546001600160a01b03808216835260a082901c61ffff16602084015260b09190911c63ffffffff166040830152600190920154909116606082015260800190565b60405180910390a25b50949350505050565b80156109b5576040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015613dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613df791906153fa565b9050613e0e6001600160a01b038516843085614a23565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613e55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7991906153fa565b905082613e8683836157bb565b146113585760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b60448201526064016109a1565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052908120805463ffffffff1691613f1083615845565b82546101009290920a63ffffffff8181021990931691831602179091556001600160a01b038581166000908152601260209081526040808320938816835292815282822061ffff87168352905220541660010390506109b5576001600160a01b03808416600081815260116020908152604080832061ffff87168085529083528184208054600181018255818652848620018054978a166001600160a01b031990981688179055549484526012835281842095845294825280832094835293905291909120805463ffffffff9092166401000000000267ffffffff0000000019909216919091179055505050565b6040516001600160a01b038381166024830152604482018390526109b591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614a5c565b6040805160808101825260008082526020820181905291810182905260608101919091526000866001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156140c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140e591906153fa565b6000898152600e6020908152604091829020825160808101845290546001600160401b038082168352600160401b8204811693830193909352600160801b81048316938201849052600160c01b9004909116606082015293509091501580614158575060408301516001600160401b0316155b6141a45760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f54505f444546494e4954494f4e5300000000000000000060448201526064016109a1565b60608201516001600160401b031615806141c9575060608301516001600160401b0316155b6142155760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f534c5f444546494e4954494f4e5300000000000000000060448201526064016109a1565b60408301516001600160401b03161561428f57600061423f8585604001518963ffffffff16614abf565b90508561427557846001600160401b0316816001600160401b03161061426657600061427f565b61427081866157ce565b61427f565b61427f81866157f5565b6001600160401b03166040840152505b60608301516001600160401b0316156143095760006142b98585606001518963ffffffff16614abf565b9050856142cf576142ca81866157f5565b6142f9565b846001600160401b0316816001600160401b0316106142ef5760006142f9565b6142f981866157ce565b6001600160401b03166060840152505b61432081858863ffffffff16856040015189613ade565b6001600160401b03908116604084015242168252606082015161434f908290869063ffffffff8a169089613bb0565b6001600160401b0390811660608401908152428216602080860191825260009b8c52600e905260409a8b90208551815492519c87015193518516600160c01b026001600160c01b03948616600160801b02949094166001600160801b039d8616600160401b026001600160801b03199094169190951617919091179a909a1691909117179097559695505050505050565b801561252b576001600160a01b0383166000908152600960205260408120829184600381111561441257614412614f3b565b600381111561442357614423614f3b565b815260200190815260200160002060008282546144409190615868565b90915550829050600381111561445857614458614f3b565b836001600160a01b0316857f52aab89a61b38ba21feecda2012e9c20aec817e5d709d0633c3fd693bb949cbb84604051612f7491815260200190565b80156109b5576109b56001600160a01b0384168383613ffe565b600060646144bc8385615469565b6144c69190615496565b9392505050565b6000620186a06144bc8385615469565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052205463ffffffff16600103614713576001600160a01b038316600090815260116020908152604080832061ffff85168452909152902080546001101561469a576001600160a01b038481166000908152601260209081526040808320938716835292815282822061ffff8616835290522054815464010000000090910463ffffffff1690829061459f906001906157bb565b815481106145af576145af61587b565b6000918252602090912001546001600160a01b0316826145d0600184615891565b63ffffffff16815481106145e6576145e661587b565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918716815260129091526040812082918461462a600185615891565b63ffffffff16815481106146405761464061587b565b60009182526020808320909101546001600160a01b03168352828101939093526040918201812061ffff881682529092529020805463ffffffff929092166401000000000267ffffffff0000000019909216919091179055505b6001600160a01b038085166000908152601260209081526040808320938716835292815282822061ffff86168352905220805467ffffffffffffffff1916905580548190806146eb576146eb6158ae565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b6001600160a01b038084166000908152601260209081526040808320938616835292815282822061ffff851683529052908120805463ffffffff1691614758836158c4565b91906101000a81548163ffffffff021916908363ffffffff16021790555050505050565b83516001600160a01b039081166000908152600b60209081526040808320546060890151928901519151630f1a62d160e31b8152939485948594859493909216926378d31688926147d8928e92908d908d908d906004016158e4565b6080604051808303816000875af11580156147f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481b919061593b565b929c919b50995090975095505050505050565b6001600160a01b038085166000908152600a6020526040812054909116908385106148d75761485d83856157bb565b9050600061486b82876157bb565b6040516321d4911360e01b81526001600160a01b038a8116600483015260248201839052919250908416906321d4911390604401600060405180830381600087803b1580156148b957600080fd5b505af11580156148cd573d6000803e3d6000fd5b5050505050614983565b508360006148e582866157bb565b9050838111156149085761490387846148fe87856157bb565b614494565b614981565b6001600160a01b0383166321d491133061492284886157bb565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561496857600080fd5b505af115801561497c573d6000803e3d6000fd5b505050505b505b61498e868883614494565b50505050505050565b60008581846149af576149aa8688615971565b6149b9565b6149b98787615971565b905060008460070b620186a08360070b6149d39190615815565b6149dd9190615815565b90506000600789900b6149f16064846159a0565b6149fb91906159a0565b90508094508360070b8560070b13614a135784614a15565b835b9a9950505050505050505050565b6040516001600160a01b03848116602483015283811660448301526064820183905261252b9186918216906323b872dd9060840161402b565b6000614a716001600160a01b03841683614b0e565b90508051600014158015614a96575080806020019051810190614a949190615413565b155b156109b557604051635274afe760e01b81526001600160a01b03841660048201526024016109a1565b600080826001600160401b0316620186a06064866001600160401b0316886001600160401b0316614af09190615469565b614afa9190615469565b614b049190615496565b613ba79190615496565b60606144c68383600084600080856001600160a01b03168486604051614b3491906154ce565b60006040518083038185875af1925050503d8060008114614b71576040519150601f19603f3d011682016040523d82523d6000602084013e614b76565b606091505b5091509150614b86868383614b90565b9695505050505050565b606082614ba557614ba082614bec565b6144c6565b8151158015614bbc57506001600160a01b0384163b155b15614be557604051639996b31560e01b81526001600160a01b03851660048201526024016109a1565b50806144c6565b805115614bfc5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0381168114610b0557600080fd5b600060208284031215614c3c57600080fd5b81356144c681614c15565b600060208284031215614c5957600080fd5b5035919050565b60048110610b0557600080fd5b600080600060608486031215614c8257600080fd5b8335614c8d81614c15565b92506020840135614c9d81614c60565b91506040840135614cad81614c15565b809150509250925092565b80356001600160401b0381168114614ccf57600080fd5b919050565b600080600060608486031215614ce957600080fd5b83359250614cf960208501614cb8565b9150604084013590509250925092565b60008060408385031215614d1c57600080fd5b8235614d2781614c60565b946020939093013593505050565b60008060408385031215614d4857600080fd5b8235614d5381614c15565b91506020830135614d6381614c60565b809150509250929050565b60008060408385031215614d8157600080fd5b8235614d2781614c15565b6020808252825182820181905260009190848201906040850190845b81811015614dcd5783516001600160a01b031683529284019291840191600101614da8565b50909695505050505050565b600080600060608486031215614dee57600080fd5b83359250602084013560028110614e0457600080fd5b929592945050506040919091013590565b600080600060608486031215614e2a57600080fd5b8335614e3581614c15565b95602085013595506040909401359392505050565b60038110610b0557600080fd5b600080600060608486031215614e6c57600080fd5b833592506020840135614e0481614e4a565b60008060008060808587031215614e9457600080fd5b843593506020850135614ea681614c60565b9250614eb460408601614cb8565b9150614ec260608601614cb8565b905092959194509250565b8015158114610b0557600080fd5b8035614ccf81614ecd565b60008060408385031215614ef957600080fd5b823591506020830135614d6381614ecd565b600080600060608486031215614f2057600080fd5b8335614f2b81614c15565b92506020840135614e0481614c15565b634e487b7160e01b600052602160045260246000fd5b60068110614f6157614f61614f3b565b9052565b87815260e08101614f796020830189614f51565b6001600160401b03968716604083015263ffffffff958616606083015293151560808201529190941660a08201529290911660c09092019190915292915050565b60a08101614fc88288614f51565b6001600160401b0395909516602082015261ffff939093166040840152901515606083015263ffffffff16608090910152919050565b600080600080600060a0868803121561501657600080fd5b8535945061502660208701614cb8565b935061503460408701614cb8565b925061504260608701614cb8565b915061505060808701614cb8565b90509295509295909350565b60008060006060848603121561507157600080fd5b833561507c81614c15565b92506020840135614c9d81614c15565b803561ffff81168114614ccf57600080fd5b803563ffffffff81168114614ccf57600080fd5b600080600080608085870312156150c857600080fd5b84356150d381614c15565b935060208501356150e381614c15565b92506150f16040860161508c565b9150614ec26060860161509e565b6000806000806080858703121561511557600080fd5b843593506020850135614ea681614e4a565b60008060006060848603121561513c57600080fd5b8335925061514c60208501614cb8565b915061515a60408501614cb8565b90509250925092565b601f8201601f191681016001600160401b038111828210171561519657634e487b7160e01b600052604160045260246000fd5b6040525050565b60405161012081016001600160401b03811182821017156151ce57634e487b7160e01b600052604160045260246000fd5b60405290565b600061012082840312156151e757600080fd5b6151ef61519d565b90506151fa82614edb565b8152602082013560208201526152126040830161509e565b604082015261522360608301614cb8565b606082015261523460808301614cb8565b608082015261524560a08301614cb8565b60a082015261525660c08301614cb8565b60c082015261526760e08301614cb8565b60e082015261010061527a818401614cb8565b9082015292915050565b6000806000808486036101e081121561529c57600080fd5b85356152a781614e4a565b94506080601f19820112156152bb57600080fd5b50604051608081018181106001600160401b03821117156152ec57634e487b7160e01b600052604160045260246000fd5b60405260208601356152fd81614c15565b815261530b6040870161508c565b6020820152606086013561531e81614c15565b604082015261532f6080870161509e565b606082015292506153438660a087016151d4565b9150614ec26101c0860161509e565b8051825263ffffffff602082015116602083015260408101511515604083015260608101516001600160401b03808216606085015280608084015116608085015250505050565b60a08101610eb58284615352565b606081016153b58286614f51565b6001600160401b039390931660208201526001600160a01b0391909116604090910152919050565b6000602082840312156153ef57600080fd5b81516144c681614c15565b60006020828403121561540c57600080fd5b5051919050565b60006020828403121561542557600080fd5b81516144c681614ecd565b60208082526009908201526821547269676765727360b81b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610eb557610eb5615453565b634e487b7160e01b600052601260045260246000fd5b6000826154a5576154a5615480565b500490565b60005b838110156154c55781810151838201526020016154ad565b50506000910152565b600082516154e08184602087016154aa565b9190910192915050565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b6020808252600e908201526d08551c9859195c9cd41bdc9d185b60921b604082015260600190565b6020808252600b908201526a57524f4e475f504841534560a81b604082015260600190565b6020808252600b908201526a1410525497d4105554d15160aa1b604082015260600190565b6101e081016155958287614f51565b60018060a01b0380865116602084015261ffff602087015116604084015280604087015116606084015250606085015163ffffffff80821660808501528551151560a0850152602086015160c08501528060408701511660e08501525050606084015161010061560f818501836001600160401b03169052565b60808601516001600160401b0390811661012086015260a0870151811661014086015260c0870151811661016086015260e0870151811661018086015290860151166101a08401525063ffffffff83166101c0830152613ba7565b6000806040838503121561567d57600080fd5b505080516020909101519092909150565b600060033d11156156a75760046000803e5060005160e01c5b90565b600060443d10156156b85790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156156e757505050505090565b82850191508151818111156156ff5750505050505090565b843d87010160208285010111156157195750505050505090565b61572860208286010187615163565b509095945050505050565b60208152600082518060208401526157528160408501602087016154aa565b601f01601f19169190910160400192915050565b805160208201516001600160e01b031980821692919060048310156157955780818460040360031b1b83161693505b505050919050565b60408101601284106157b1576157b1614f3b565b9281526020015290565b81810381811115610eb557610eb5615453565b6001600160401b038281168282160390808211156157ee576157ee615453565b5092915050565b6001600160401b038181168382160190808211156157ee576157ee615453565b80820260008212600160ff1b8414161561583157615831615453565b8181058314821517610eb557610eb5615453565b600063ffffffff80831681810361585e5761585e615453565b6001019392505050565b80820180821115610eb557610eb5615453565b634e487b7160e01b600052603260045260246000fd5b63ffffffff8281168282160390808211156157ee576157ee615453565b634e487b7160e01b600052603160045260246000fd5b600063ffffffff8216806158da576158da615453565b6000190192915050565b8681526001600160a01b038616602082015261ffff8516604082015261014081016159126060830186615352565b836101008301526005831061592957615929614f3b565b82610120830152979650505050505050565b6000806000806080858703121561595157600080fd5b505082516020840151604085015160609095015191969095509092509050565b600782810b9082900b03677fffffffffffffff198112677fffffffffffffff82131715610eb557610eb5615453565b6000826159af576159af615480565b600160ff1b8214600019841416156159c9576159c9615453565b50059056fea2646970667358221220dda688b0ed3677ee0cecc93216cfa1c23d52c51d3de4b5754befe318ad663cfc64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.