Source Code
Overview
S Balance
S Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| _become | 53050101 | 85 days ago | IN | 0 S | 0.001812 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
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 {ILynxVersionedContract} from "../interfaces/ILynxVersionedContract.sol";
import "./TradingFloorStorage.sol";
import "./TradingFloorProxy.sol";
/**
* @title TradingFloorV1
* @notice The TradingFloor contract is the main contract for the Lynx trading platform.
* It handles the opening, updating and closing of positions.
*
* @dev Version History:
* - v1.00 (1000): Initial version with core trading functionality
* - Per-pair trader tracking using pairTraders and pairTradersInfo mappings
* - Basic position management with maxTradesPerPair limit
* - Standard fee collection and position lifecycle management
*
* - v1.01 (1010): Global trader tracking system implementation
* - Replaced per-pair trader tracking with global trader array
* - Added `traders` array for all active traders across all pairs
* - Added `tradersIndex` mapping with 1-based indexing (0 = not in array)
* - Added `activePositionIdsByTrader` for global position tracking
* - Added `positionIdToActivePositionIndex` for O(1) position removal
* - Changed `maxTradesPerPair` to `maxTradesPerTrader` for global limits
* - Implemented swap-and-pop pattern for efficient trader removal
* - Deprecated old mappings: `pairTraders` → `deprecated_pairTraders`,
* `pairTradersInfo` → `deprecated_pairTradersInfo`
* - Benefits: Better gas efficiency, simplified cross-pair management, O(1) operations
*
* - v1.01.1 (1011): Limits update
* - Modified SL/TP update validation to check against current price instead of open price
*
* - v1.01.2 (1012): Bug fixes
* - Fixed issue with trader removal when not present in traders array
*
* - v1.01.3 (1013): Trader tracking consistency fix
* - Added IncorrectTraderIndex event for tracking discrepancies
* - Enhanced decreaseOrRemoveFromTradersLists to handle corrupted tradersIndex mapping
* - Prevents incorrect trader removal when index points to wrong address
* - Cleans up stale mappings allowing natural self-healing on next position open
*
* - v1.01.4 (1014): Trust Triggers SL execution price
* - Changed closeExistingPosition_Limit to use effectivePrice instead of positionLimitInfo.sl for SL triggers
* - Enables TriggersV1 to calculate buffered execution price when market gaps through SL
* - Validation still ensures effectivePrice is on correct side of SL (security maintained)
*/
contract TradingFloorV1 is
TradingFloorV1Storage,
ITradingFloorV1Functionality,
ILynxVersionedContract,
LexErrors
{
using SafeERC20 for IERC20;
// ***** Constants (ILynxVersionedContract interface) *****
string public constant CONTRACT_NAME = "TradingFloorV1";
string public constant CONTRACT_VERSION = "1014"; // 1.01.4 - Trust Triggers SL execution price
// ***** 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
);
// Old event, left for indexing purposes
event PendingPositionStored(
bytes32 indexed positionId,
PositionPhase phase,
PositionRequestIdentifiers_Old requestIdentifiers,
PositionRequestParams requestParams,
uint32 _spreadReductionF
);
event PendingPositionStoredV1010(
bytes32 indexed positionId,
PositionPhase phase,
uint32 index,
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
);
event IncorrectTraderIndex(
address indexed trader,
uint256 traderIndex,
address foundTraderAddress
);
// ***** 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 (ILynxVersionedContract interface) *****
function getContractName() external pure override returns (string memory) {
return CONTRACT_NAME;
}
function getContractVersion() external pure override returns (string memory) {
return CONTRACT_VERSION;
}
// ***** 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);
}
function deprecated_pairTradersArray(
address _asset,
uint _pairIndex
) external view returns (address[] memory) {
return deprecated_pairTraders[_asset][_pairIndex];
}
/**
* @notice Returns the length of the global traders array
* @dev Part of the v1.01 global trader tracking system
* @return Number of traders with at least one active position
*/
function tradersAmount() external view returns (uint256) {
return traders.length;
}
/**
* @notice Gets the next position index for a trader to use in position ID generation
* @dev Part of the v1.01 global tracking system. Indices start at 11 to avoid
* collision with legacy positions. This ensures unique position IDs across
* all pairs for a given trader.
* @param _trader The trader address
* @return The next available position index for this trader
*/
function getNextPositionIndexForTrader(
address _trader
) public view returns (uint32) {
uint32 lastUsedIndex = pairTradersLastUsedPositionIndex[_trader];
require(lastUsedIndex < type(uint32).max, "POSITION_INDEX_OVERFLOW");
// If this is the first position for this trader,
// start from index 11 to avoid collision with existing positions
if (lastUsedIndex < 11) {
return 11;
}
return lastUsedIndex + 1;
}
/**
* @notice Returns all active position IDs for a trader across ALL pairs
* @dev Part of the v1.01 global tracking system. This replaces the old per-pair
* position tracking with a unified view of all trader positions.
* @param _trader The trader address
* @return Array of active position IDs across all trading pairs
*/
function getActivePositionIdsForTrader(
address _trader
) external view returns (bytes32[] memory) {
return activePositionIdsByTrader[_trader];
}
function getActivePositionsAmountForTrader(
address _trader
) external view returns (uint256) {
return activePositionIdsByTrader[_trader].length;
}
// ***** 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_TRADER) {
name = "maxTradesPerTrader";
maxTradesPerTrader = 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(
activePositionIdsByTrader[_requestIdentifiers.trader].length <
maxTradesPerTrader,
"MAX_TRADES_PER_TRADER"
);
uint32 index;
(positionId, index) = storeIdentifiersIfNeeded(
_requestIdentifiers.settlementAsset,
_requestIdentifiers.trader,
_requestIdentifiers.pairId
);
takeSettlement(
_requestIdentifiers.settlementAsset,
_requestIdentifiers.trader,
_requestParams.collateral
);
// Add/Increase in traders
increaseOrAddToTradersLists(_requestIdentifiers.trader);
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 PendingPositionStoredV1010(
positionId,
phase,
index,
_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 = effectivePrice; // Trust Triggers SL execution price (with buffer)
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");
}
// Ensure the new params are valid
requireValidOpenTradeParameters(
p.long,
effectivePrice,
effectivePrice,
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");
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,
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
) internal returns (bytes32 positionId, uint32 index) {
index = getNextPositionIndexForTrader(trader);
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;
// Update lastUsedPositionIndex
pairTradersLastUsedPositionIndex[trader] = index;
// Add to active position IDs tracking
addToActivePositionIds(trader, positionId);
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,
_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,
_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 traders
decreaseOrRemoveFromTradersLists(identifiers.trader);
// Remove from active position IDs tracking
removeFromActivePositionIds(identifiers.trader, _positionId);
// 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,
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
decreaseOrRemoveFromTradersLists(trader);
// Remove from active position IDs tracking
removeFromActivePositionIds(trader, positionId);
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 *****
/**
* @notice Adds a trader to the global traders array if this is their first position
* @dev Part of v1.01 global tracking. Called AFTER position is added to activePositionIdsByTrader.
* Uses 1-based indexing in tradersIndex mapping (0 = not in array).
* This replaces the old per-pair trader tracking system.
* @param trader The trader address to potentially add to the global array
*/
function increaseOrAddToTradersLists(address trader) internal {
// Check if this is the first position for this trader across ALL pairs
// Note: Position has already been added to activePositionIdsByTrader when this is called
if (activePositionIdsByTrader[trader].length == 1) {
// Add trader to global array
traders.push(trader);
// Store 1-based index (array position + 1)
tradersIndex[trader] = traders.length;
}
// If not first position, trader is already in the array
}
/**
* @notice Removes a trader from the global array if this is their last position
* @dev Part of v1.01 global tracking. Called BEFORE position is removed from activePositionIdsByTrader.
* Uses swap-and-pop pattern for O(1) removal:
* 1. Move last trader to the removed trader's position
* 2. Update the moved trader's index
* 3. Delete the removed trader's index
* 4. Pop the last element
* @param trader The trader address to potentially remove from the global array
*/
function decreaseOrRemoveFromTradersLists(address trader) internal {
// Check if this is the last position for this trader across ALL pairs
// Note: Position has NOT been removed from activePositionIdsByTrader yet
if (activePositionIdsByTrader[trader].length == 1) {
// Sanity Checks
uint256 _traderIndex = tradersIndex[trader];
if (_traderIndex == 0) {
// Trader not in the array, SHOULD NOT HAPPEN, a fix for past issue
emit IncorrectTraderIndex(trader, 0, address(0));
return;
}
if (trader != traders[_traderIndex - 1]) {
// Index mapping is corrupted, SHOULD NOT HAPPEN, a fix for past issue
delete tradersIndex[trader];
emit IncorrectTraderIndex(
trader,
_traderIndex,
traders[_traderIndex - 1]
);
return;
}
// Use swap-and-pop pattern for O(1) removal
if (traders.length > 1) {
// Move last trader to the removed trader's position (convert 1-based to 0-based)
traders[_traderIndex - 1] = traders[traders.length - 1];
// Update the moved trader's index to the new position
tradersIndex[traders[_traderIndex - 1]] = _traderIndex;
}
// Clear the removed trader's index (set to 0 = not in array)
delete tradersIndex[trader];
// Remove the last element
traders.pop();
}
// If not the last position, keep trader in the global array
}
/**
* @notice Adds a position ID to the trader's active positions array
* @dev Part of v1.01 global tracking. Maintains a dynamic array of all active
* positions for each trader across all pairs. Uses 1-based indexing in
* the mapping for efficient existence checks (0 = not in array).
* @param trader The trader who owns the position
* @param positionId The position ID to add to the trader's active list
*/
function addToActivePositionIds(address trader, bytes32 positionId) internal {
bytes32[] storage activeIds = activePositionIdsByTrader[trader];
activeIds.push(positionId);
// Store as 1-based index (array position + 1) for O(1) lookups
// 0 = not in array, 1 = at array[0], 2 = at array[1], etc.
positionIdToActivePositionIndex[trader][positionId] = activeIds.length;
}
/**
* @notice Removes a position ID from the trader's active positions array
* @dev Part of v1.01 global tracking. Uses swap-and-pop pattern for O(1) removal:
* 1. Get the position's index from the mapping
* 2. Move the last position ID to this index
* 3. Update the moved position's index in the mapping
* 4. Delete the removed position's index
* 5. Pop the last element
* @param trader The trader who owns the position
* @param positionId The position ID to remove from the trader's active list
*/
function removeFromActivePositionIds(
address trader,
bytes32 positionId
) internal {
uint256 storedArrayIndex = positionIdToActivePositionIndex[trader][
positionId
];
// Only process if the position is in the array (storedArrayIndex > 0)
if (storedArrayIndex > 0) {
bytes32[] storage activeIds = activePositionIdsByTrader[trader];
// Convert from 1-based to 0-based for array access
uint256 arrayIndex = storedArrayIndex - 1;
// If not the last element, swap with last
if (arrayIndex < activeIds.length - 1) {
bytes32 lastPositionId = activeIds[activeIds.length - 1];
activeIds[arrayIndex] = lastPositionId;
// Update the moved element's array index mapping (store as 1-based)
positionIdToActivePositionIndex[trader][
lastPositionId
] = storedArrayIndex;
}
// Remove last element
activeIds.pop();
// Clean up the mapping
delete positionIdToActivePositionIndex[trader][positionId];
}
}
// ***** 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.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
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 Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
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 silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: 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
/**
* @dev scale for leverage.
* 10,000 = 100x
* 1,000 = 10x
* 100 = 1x
* 10 = 0.1x
* 1 = 0.01x (smallest unit)
*/
uint256 public constant LEVERAGE_SCALE = 100; // 2 decimal points
/**
* @dev scale for fractions.
* 100,000 = 100%
* 100,000 = 10%
* 1,000 = 1%
* 100 = 0.1%
* 10 = 0.01%
* 1 = 0.001% (smallest unit)
*/
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);
// Get funding rate for a specific accountant (for progressive ramp-up feature)
function getFundingRateForAccountant(
address accountant,
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;
interface ILynxVersionedContract {
/**
* @notice Returns the name of the contract
*/
function getContractName() external view returns (string memory);
/**
* @notice Returns the version of the contract
* @dev units are scaled by 1000 (1,000 = 1.00, 1,120 = 1.12)
*/
function getContractVersion() external view returns (string memory);
}// 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 deprecated_pairTradersArray(
address _asset,
uint _pairIndex
) external view returns (address[] memory);
function traders(uint256 index) external view returns (address);
function tradersAmount() external view returns (uint256);
function getNextPositionIndexForTrader(
address _trader
) external view returns (uint32);
function getActivePositionIdsForTrader(
address _trader
) external view returns (bytes32[] memory);
function getActivePositionsAmountForTrader(
address _trader
) external view returns (uint256);
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 maxTradesPerTrader() 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_TRADER,
MAX_SL_F,
MAX_SANITY_PROFIT_F
}
/**
* @dev Memory struct for identifiers
*/
struct PositionRequestIdentifiers {
address trader;
uint16 pairId;
address settlementAsset;
}
/**
* @dev Memory struct for identifiers
*/
struct PositionRequestIdentifiers_Old {
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 deprecated_positionsCounter; // 04 bytes - DEPRECATED: Use activePositionIdsByTrader.length instead
uint32 positionInArray; // 04 bytes (the index + 1)
//! Note : Can NOT (!) 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 *****
// Maximum number of open positions a trader can have globally across all pairs
// Replaces the old maxTradesPerPair with global position limiting
uint public maxTradesPerTrader;
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;
// ***** DEPRECATED: Per-pair trader tracking (kept for backward compatibility) *****
// asset => pair id => traders list
mapping(address => mapping(uint => address[])) public deprecated_pairTraders;
// asset => trader => pair id => index in traders list
mapping(address => mapping(address => mapping(uint => PairTraderInfo)))
public deprecated_pairTradersInfo;
// ***** NEW: Global trader tracking system (introduced in v1.01) *****
// Global array of all traders with active positions across any pair
// Traders are added when opening their first position and removed when closing their last
address[] public traders;
// Maps trader address to their index in the traders array (1-based indexing)
// 0 = not in array (default), 1 = at array[0], 2 = at array[1], etc.
// This enables O(1) existence checks and efficient array management
mapping(address => uint) public tradersIndex;
// Tracks the last used position index for generating unique position IDs
// Increments with each new position opened by the trader
mapping(address => uint32) public pairTradersLastUsedPositionIndex;
// Maps trader to their list of active position IDs across all pairs
// Enables efficient iteration through only active positions for a trader
// Positions are added on open and removed on close using swap-and-pop
mapping(address => bytes32[]) public activePositionIdsByTrader;
// Maps position ID to its index in the trader's activePositionIdsByTrader array (1-based)
// 0 = not in array, 1 = at array[0], etc.
// Enables O(1) removal from activePositionIdsByTrader when closing positions
mapping(address => mapping(bytes32 => uint256))
public positionIdToActivePositionIndex;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"enum LexErrors.CapType","name":"","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"CapError","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":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"traderIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"foundTraderAddress","type":"address"}],"name":"IncorrectTraderIndex","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_Old","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":"enum TradingEnumsV1.PositionPhase","name":"phase","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"index","type":"uint32"},{"components":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint16","name":"pairId","type":"uint16"},{"internalType":"address","name":"settlementAsset","type":"address"}],"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":"PendingPositionStoredV1010","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":"CONTRACT_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTRACT_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"activePositionIdsByTrader","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","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":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"deprecated_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":"deprecated_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":"deprecated_pairTradersInfo","outputs":[{"internalType":"uint32","name":"deprecated_positionsCounter","type":"uint32"},{"internalType":"uint32","name":"positionInArray","type":"uint32"}],"stateMutability":"view","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":"address","name":"_trader","type":"address"}],"name":"getActivePositionIdsForTrader","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_trader","type":"address"}],"name":"getActivePositionsAmountForTrader","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_trader","type":"address"}],"name":"getNextPositionIndexForTrader","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","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":"maxTradesPerTrader","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"}],"name":"pairTradersLastUsedPositionIndex","outputs":[{"internalType":"uint32","name":"","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":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positionIdToActivePositionIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"uint256","name":"","type":"uint256"}],"name":"traders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradersAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tradersIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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
608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615c8f80620000336000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806382571409116101de578063b71f3cfe1161010f578063ece938cf116100ad578063f555f6971161007c578063f555f69714610aed578063f5f5ba7214610b0d578063f851a44014610b37578063f9b9484e14610b4a57600080fd5b8063ece938cf14610a5b578063ef6ecc5514610a64578063f2eb245e14610ac4578063f51f3fd314610ae457600080fd5b8063ddf474f1116100e9578063ddf474f1146109cd578063e640f33b14610a15578063eb48914014610a28578063ec7f8a3a14610a3b57600080fd5b8063b71f3cfe1461099c578063c07f9921146109a7578063ca3a3a82146109ba57600080fd5b806395be50501161017c578063a40d726811610156578063a40d726814610947578063aaf5eb681461095a578063acfd6b9214610969578063ad1f2b561461099457600080fd5b806395be5050146108a65780639ff69ffa14610921578063a2a25ea61461093457600080fd5b80638f7a8fb5116101b85780638f7a8fb5146107e257806390f24cac1461085d57806393a7f6a71461087057806394a1e6e51461089e57600080fd5b806382571409146107a657806386dc4975146107af5780638aa10435146107c257600080fd5b8063396f7b23116102c357806368f296a51161026157806376d901be1161023057806376d901be146107435780637b1039991461077657806380193b261461078957806380a7f3d41461079357600080fd5b806368f296a5146106c15780636e01af8d146106e7578063725b7d52146106fa57806374d8b78e1461071a57600080fd5b80634ebe5c331161029d5780634ebe5c33146105f35780635c60da1b14610606578063614d08f81461061957806366307a4f1461064657600080fd5b8063396f7b23146105ad5780633ad6f124146105c05780633b17a497146105d357600080fd5b80631ea9af6b1161033057806324b22a1f1161030a57806324b22a1f1461052c578063267822471461053f57806330d073d01461055257806338b903331461057d57600080fd5b80631ea9af6b146104e95780632457bc3a146104fc5780632485f3f11461050457600080fd5b8063135e563d1161036c578063135e563d1461048557806318fa4714146104985780631961aba0146104ad5780631d504dc6146104d657600080fd5b8063010570851461039357806303b90a87146103b9578063042e37c5146103fa575b600080fd5b6103a66103a1366004614fdf565b610bac565b6040519081526020015b60405180910390f35b6103e26103c7366004615123565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103b0565b610449610408366004615140565b600c60205260009081526040902080546001909101546001600160a01b0380831692600160a01b810461ffff1692600160b01b90910463ffffffff16911684565b604080516001600160a01b03958616815261ffff909416602085015263ffffffff909216918301919091529190911660608201526080016103b0565b6103e2610493366004615140565b611107565b6104ab6104a6366004615166565b611131565b005b6103a66104bb366004615123565b6001600160a01b031660009081526016602052604090205490565b6104ab6104e4366004615123565b611200565b6104ab6104f73660046151b1565b61134e565b6013546103a6565b610517610512366004615123565b6113e4565b60405163ffffffff90911681526020016103b0565b6104ab61053a3660046151e6565b61147e565b6001546103e2906001600160a01b031681565b6103a6610560366004615212565b600960209081526000928352604080842090915290825290205481565b6105a0604051806040016040528060048152602001630c4c0c4d60e21b81525081565b6040516103b0919061526f565b6003546103e2906001600160a01b031681565b6103a66105ce3660046152a2565b61171d565b6105e66105e1366004615123565b61174e565b6040516103b091906152c0565b6104ab610601366004615304565b6117ba565b6002546103e2906001600160a01b031681565b6105a06040518060400160405280600e81526020016d54726164696e67466c6f6f72563160901b81525081565b61068e610654366004615140565b600e602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b03958616815293851660208501529184169183019190915290911660608201526080016103b0565b6105176106cf366004615123565b60156020526000908152604090205463ffffffff1681565b6104ab6106f5366004615340565b61187e565b61070d6107083660046152a2565b611c14565b6040516103b09190615367565b6103e2610728366004615123565b600a602052600090815260409020546001600160a01b031681565b610766610751366004615140565b60086020526000908152604090205460ff1681565b60405190151581526020016103b0565b6004546103e2906001600160a01b031681565b6103a6620186a081565b6104ab6107a13660046153a8565b611c94565b6103a660075481565b6104ab6107bd3660046153ec565b6120e6565b6040805180820190915260048152630c4c0c4d60e21b60208201526105a0565b61084a6107f0366004615140565b600d602052600090815260409020805460019091015460ff808216916001600160401b03610100820481169263ffffffff600160481b8404811693600160681b810490921692600160701b83041691600160b01b90041687565b6040516103b0979695949392919061543b565b6103e261086b366004615490565b612179565b61076661087e366004615123565b6001600160a01b039081166000908152600a602052604090205416151590565b6103a66121be565b6109106108b4366004615140565b6000908152600d6020818152604080842060010154600c835293205491905260ff8083169361010084046001600160401b031693600160a01b90930461ffff1692600160681b810490921691600160b01b900463ffffffff1690565b6040516103b09594939291906154c5565b6104ab61092f366004615509565b6121cf565b6104ab610942366004615567565b612416565b6103a6610955366004615597565b612538565b6103a6670de0b6b3a764000081565b6103a66109773660046152a2565b601760209081526000928352604080842090915290825290205481565b6103a6606481565b6103a6633b9aca0081565b6104ab6109b53660046155e4565b6125a7565b6104ab6109c836600461560c565b612c64565b61068e6109db366004615140565b600f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b6104ab610a2336600461560c565b612e15565b6104ab610a363660046151b1565b612fa6565b6103a6610a49366004615123565b60146020526000908152604090205481565b6103a660055481565b610aa7610a72366004615648565b601260209081526000938452604080852082529284528284209052825290205463ffffffff8082169164010000000090041682565b6040805163ffffffff9384168152929091166020830152016103b0565b6103a6610ad2366004615140565b60106020526000908152604090205481565b6103a660065481565b610b00610afb366004615140565b61303c565b6040516103b091906156bf565b60408051808201909152600e81526d54726164696e67466c6f6f72563160901b60208201526105a0565b6000546103e2906001600160a01b031681565b610b9d610b58366004615140565b6000908152600d60209081526040808320600190810154600c90935292209091015460ff8216926101009092046001600160401b0316916001600160a01b0390911690565b6040516103b0939291906156cd565b6004805460405163731aa5f960e01b815233928101929092526000916001600160a01b039091169063731aa5f990602401602060405180830381865afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1e9190615703565b610c435760405162461bcd60e51b8152600401610c3a90615720565b60405180910390fd5b610c6b84604001516001600160a01b039081166000908152600a602052604090205416151590565b610cb75760405162461bcd60e51b815260206004820152601e60248201527f4e4f4e5f535550504f525445445f534554544c454d454e545f415353455400006044820152606401610c3a565b60208085015161ffff1660009081526008909152604090205460ff1615610cf05760405162461bcd60e51b8152600401610c3a90615748565b6001856002811115610d0457610d04615411565b1480610d2157506002856002811115610d1f57610d1f615411565b145b610d665760405162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f4f524445525f5459504560501b6044820152606401610c3a565b610dab836000015184606001516001600160401b031685608001516001600160401b03168660a001516001600160401b03168760c001516001600160401b0316613164565b60055484516001600160a01b031660009081526016602052604090205410610e0d5760405162461bcd60e51b815260206004820152601560248201527426a0ac2faa2920a222a9afa822a92faa2920a222a960591b6044820152606401610c3a565b6000610e26856040015186600001518760200151613246565b8092508193505050610e458560400151866000015186602001516133b7565b8451610e50906134fc565b6000828152600d60205260409020805415610e975760405162461bcd60e51b8152602060048201526007602482015266125117d554d15160ca1b6044820152606401610c3a565b600180820180548751604089015163ffffffff908116600160481b026cffffffff00000000000000000019921515600160681b0260ff60681b19928b16600160b01b02929092166cffffffff0000000000000000ff60681b1990941693909317171617905560208601518255600090886002811115610f1857610f18615411565b14610f24576002610f27565b60015b9050808260010160006101000a81548160ff02191690836005811115610f4f57610f4f615411565b0217905550428260010160016101000a8154816001600160401b0302191690836001600160401b031602179055506000600e600086815260200190815260200160002090508660a001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508660c001518160000160186101000a8154816001600160401b0302191690836001600160401b031602179055506000600f6000878152602001908152602001600020905087606001518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555087608001518160000160086101000a8154816001600160401b0302191690836001600160401b031602179055508760e001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508761010001518160000160186101000a8154816001600160401b0302191690836001600160401b03160217905550857f835de04f5a930b169d6564c8f1c5f91f89abd9ea026b7488c94452abb900cc7484878c8c8c6040516110f295949392919061576d565b60405180910390a25050505050949350505050565b6013818154811061111757600080fd5b6000918252602090912001546001600160a01b0316905081565b6004805460405163a8e36e5b60e01b81526001600160a01b038681169382019390935291169063a8e36e5b90602401602060405180830381865afa15801561117d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a19190615851565b6001600160a01b0316336001600160a01b0316146111f05760405162461bcd60e51b815260206004820152600c60248201526b10a332b2b9a6b0b730b3b2b960a11b6044820152606401610c3a565b6111fb838383613578565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561123e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112629190615851565b6001600160a01b0316336001600160a01b0316146112b15760405162461bcd60e51b815260206004820152600c60248201526b10b83937bc3c9730b236b4b760a11b6044820152606401610c3a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af11580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061586e565b1561134b5760405162461bcd60e51b8152600401610c3a9060208082526004908201526319985a5b60e21b604082015260600190565b50565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb9190615703565b6113d75760405162461bcd60e51b8152600401610c3a90615887565b6111fb836002848461369b565b6001600160a01b03811660009081526015602052604081205463ffffffff9081169081106114545760405162461bcd60e51b815260206004820152601760248201527f504f534954494f4e5f494e4445585f4f564552464c4f570000000000000000006044820152606401610c3a565b600b8163ffffffff16101561146c5750600b92915050565b6114778160016158c0565b9392505050565b6000546001600160a01b031633146114c55760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b6044820152606401610c3a565b600081116115065760405162461bcd60e51b815260206004820152600e60248201526d43414e4e4f545f42455f5a45524f60901b6044820152606401610c3a565b6060600183600381111561151c5761151c615411565b03611555575060408051808201909152601281527136b0bc2a3930b232b9a832b92a3930b232b960711b602082015260058290556116d0565b600283600381111561156957611569615411565b036115f857606461157e620186a060326158e4565b6115889190615911565b8210156115d15760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b6044820152606401610c3a565b506040805180820190915260068082526536b0bc29b62360d11b60208301528290556116d0565b600383600381111561160c5761160c615411565b0361169a5761161f620186a060026158e4565b8210156116685760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b6044820152606401610c3a565b5060408051808201909152601081526f36b0bc29b0b734ba3ca83937b334ba2360811b602082015260078290556116d0565b60405162461bcd60e51b815260206004820152600b60248201526a155394d5541413d495115160aa1b6044820152606401610c3a565b806040516116de9190615925565b604051908190038120838252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab9060200160405180910390a2505050565b6016602052816000526040600020818154811061173957600080fd5b90600052602060002001600091509150505481565b6001600160a01b0381166000908152601660209081526040918290208054835181840281018401909452808452606093928301828280156117ae57602002820191906000526020600020905b81548152602001906001019080831161179a575b50505050509050919050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615703565b6118735760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c5472696767657273290000000000006044820152606401610c3a565b6111fb338484613d2f565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa1580156118c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118eb9190615703565b6119375760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c5472696767657273290000000000006044820152606401610c3a565b6119456064620186a0615911565b81111561198b5760405162461bcd60e51b81526020600482015260146024820152734645455f4652414354494f4e5f544f4f5f42494760601b6044820152606401610c3a565b6000838152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff1660058111156119ca576119ca615411565b60058111156119db576119db615411565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b86041615156060870152600160701b85049093166080860152600160b01b90930490921660a0909301929092526000878152600d9091522054909150611a725760405162461bcd60e51b8152600401610c3a90615941565b6000848152600c6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1694830194909452600160b01b900463ffffffff16938101939093526001908101549091166060830152846002811115611ae157611ae1615411565b03611b4357600182602001516005811115611afe57611afe615411565b14611b3e5760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa6a0a925a2aa2fa7a92222a960811b6044820152606401610c3a565b611bee565b6002846002811115611b5757611b57615411565b03611bb357600282602001516005811115611b7457611b74615411565b14611b3e5760405162461bcd60e51b815260206004820152600f60248201526e2727aa2fa624a6a4aa2fa7a92222a960891b6044820152606401610c3a565b60405162461bcd60e51b815260206004820152601060248201526f57524f4e475f4f524445525f5459504560801b6044820152606401610c3a565b611c0d8582600001518360600151856000015186606001518833613e40565b5050505050565b6001600160a01b0382166000908152601160209081526040808320848452825291829020805483518184028101840190945280845260609392830182828015611c8657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c68575b505050505090505b92915050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d019190615703565b611d1d5760405162461bcd60e51b8152600401610c3a90615887565b6000848152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff166005811115611d5c57611d5c615411565b6005811115611d6d57611d6d615411565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a0909101528051909150611ded5760405162461bcd60e51b8152600401610c3a90615941565b6000858152600e60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b90910490911660608201529080806002886003811115611e5c57611e5c615411565b03611eb9578460800151611e895783606001516001600160401b0316866001600160401b03161015611ea4565b83606001516001600160401b0316866001600160401b031611155b925050506001600160401b0384166002611f9e565b6001886003811115611ecd57611ecd615411565b03611f30578460800151611efa5783604001516001600160401b0316866001600160401b03161115611f15565b83604001516001600160401b0316866001600160401b031610155b925083604001516001600160401b0316915060019050611f9e565b6003886003811115611f4457611f44615411565b03611f60575060019150506001600160401b0384166003611f9e565b60405162461bcd60e51b81526020600482015260136024820152722ba927a723afa624a6a4aa2faa2924a3a3a2a960691b6044820152606401610c3a565b82611fdb5760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b6044820152606401610c3a565b6000806000611feb8c8686613f12565b91945092509050600384600481111561200657612006615411565b036120735787608001516120265780896001600160401b03161015612034565b80896001600160401b031611155b9550856120735760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b6044820152606401610c3a565b8a600381111561208557612085615411565b604080516001600160401b038c16815260208101849052908101859052606081018490528d907fe67823c5c7b61d690bab4b46031d192b68f898b47bdf7daffbddff8e24aaf9bd9060800160405180910390a3505050505050505050505050565b6000546001600160a01b0316331461212d5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b6044820152606401610c3a565b600082815260086020526040808220805460ff19168415159081179091559051909184917f996384f9c771a575699aadc5e543fb849613b350a1b29584a1ecca98d2cfc1709190a35050565b601160205282600052604060002060205281600052604060002081815481106121a157600080fd5b6000918252602090912001546001600160a01b0316925083915050565b6121cc6064620186a0615911565b81565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223c9190615703565b6122585760405162461bcd60e51b8152600401610c3a90615720565b6000858152600d602052604090206002600182015460ff16600581111561228157612281615411565b1461229e5760405162461bcd60e51b8152600401610c3a9061596b565b6000868152600c6020908152604080832054600160a01b900461ffff168352600890915290205460ff16156122e55760405162461bcd60e51b8152600401610c3a90615748565b61232781600101600d9054906101000a900460ff16866001600160401b0316866001600160401b0316866001600160401b0316866001600160401b0316613164565b60018101805468ffffffffffffffff001916610100426001600160401b0390811691909102919091179091556000878152600e6020908152604080832080546001600160801b0316600160801b8987169081026001600160c01b031691909117600160c01b898816908102919091178355600f85529483902080548c88166001600160801b03199091168117600160401b988d169889021782558451928352948201959095529182019290925260608101939093529188907f098a3c0f7acdf2c147440d705e162d395db886273731a238b250793cde346d859060800160405180910390a25050505050505050565b6004546001600160a01b0316331461245c5760405162461bcd60e51b815260206004820152600960248201526821526567697374727960b81b6044820152606401610c3a565b6001600160a01b038381166000908152600a602052604090205416156124c45760405162461bcd60e51b815260206004820152601760248201527f41535345545f414c52454144595f535550504f525445440000000000000000006044820152606401610c3a565b6001600160a01b038084166000818152600a6020908152604080832080548689166001600160a01b03199182168117909255600b9093528184208054968816969093168617909255519092917fe34fb4592f12d191480ae66f1051ba82ee53c518b07f632579da8d40a74c77c891a4505050565b60408051606095861b6bffffffffffffffffffffffff199081166020808401919091529590961b909516603486015260f09290921b6001600160f01b031916604885015260e01b6001600160e01b031916604a8401528051602e818503018152604e9093019052815191012090565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126149190615703565b6126305760405162461bcd60e51b8152600401610c3a90615887565b6000848152600d60209081526040808320600e8352818420600c845293829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1696830196909652600160b01b900463ffffffff169381019390935260010154909216606082015281549192916126ba5760405162461bcd60e51b8152600401610c3a90615941565b6003600184015460ff1660058111156126d5576126d5615411565b146126f25760405162461bcd60e51b8152600401610c3a9061596b565b80516001600160a01b039081166000908152600b60205260408120549091169080600189600281111561272757612727615411565b036129e25760006127c8846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612793919061586e565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16614116565b9050886001600160401b0316816001600160401b03161461281d5760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b6044820152606401610c3a565b85546001600160401b03600160801b90910481169082160361286b5760405162461bcd60e51b8152602060048201526007602482015266053414d455f54560cc1b6044820152606401610c3a565b8092508560000160189054906101000a90046001600160401b03169150428660000160006101000a8154816001600160401b0302191690836001600160401b03160217905550836001600160a01b0316633cdc20f88c876060015188602001518b600001548c60010160099054906101000a900463ffffffff168d600101600d9054906101000a900460ff168e600101600e9054906101000a90046001600160401b03168e60000160109054906101000a90046001600160401b03168c6040518a63ffffffff1660e01b81526004016129aa999897969594939291909889526001600160a01b0397909716602089015261ffff959095166040880152606087019390935263ffffffff919091166080860152151560a08501526001600160401b0390811660c085015290811660e0840152166101008201526101200190565b600060405180830381600087803b1580156129c457600080fd5b505af11580156129d8573d6000803e3d6000fd5b5050505050612b73565b60028960028111156129f6576129f6615411565b0361169a576000612a97846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061586e565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff166141e8565b9050886001600160401b0316816001600160401b031614612aec5760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b6044820152606401610c3a565b85546001600160401b03600160c01b909104811690821603612b3a5760405162461bcd60e51b815260206004820152600760248201526614d0535157d4d360ca1b6044820152606401610c3a565b8554426001600160401b03908116600160401b026fffffffffffffffff0000000000000000198316178855600160801b90910416925090505b6001860154612b9f90600160681b900460ff166001600160401b03898116908190868116908616613164565b84546001600160401b03838116600160801b0267ffffffffffffffff60801b19918416600160c01b02919091166001600160801b0390921691909117178555886002811115612bf057612bf0615411565b846020015161ffff168b7f90bbb7e2b715065bd66ba75a34fca9b65694d5e75327dd0873a5e3e68837766789600101600d9054906101000a900460ff168c604051612c5092919091151582526001600160401b0316602082015260400190565b60405180910390a450505050505050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd19190615703565b612ced5760405162461bcd60e51b8152600401610c3a90615887565b6000838152600f6020908152604091829020825160808101845290546001600160401b038082168352600160401b82048116938301849052600160801b8204811694830194909452600160c01b90049092166060830152612d605760405162461bcd60e51b8152600401610c3a90615941565b80516001600160401b0380841691161180612d905750816001600160401b031681602001516001600160401b0316105b15612da657612da130856001613d2f565b612e0f565b6000806000612dc087866001600160401b03166004613f12565b6040805182815260208101859052908101839052929550909350915087907f9912c2c8197504aea5a1b52b98eeae3f4aecabe190feebc292455c355d4297cb9060600160405180910390a25050505b50505050565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612e5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e829190615703565b612e9e5760405162461bcd60e51b8152600401610c3a90615720565b6000838152600d602052604090208054612eca5760405162461bcd60e51b8152600401610c3a90615941565b6003600182015460ff166005811115612ee557612ee5615411565b14612f025760405162461bcd60e51b8152600401610c3a9061596b565b6001810180546001600160401b034281166101000268ffffffffffffffffff19909216919091176004179091556000858152600f60209081526040918290208054868516600160401b81026001600160801b03199092169589169586179190911782558351948552918401919091529186917fb7bb5d6820a30953d2858e9c448319c4cebbc70c347961e25f1adfff46566689910160405180910390a25050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130139190615703565b61302f5760405162461bcd60e51b8152600401610c3a90615887565b6111fb836001848461369b565b6040805160a081018252600080825260208083018290528284018290526060830182905260808301829052848252600d8152838220845160e0810190955280548552600181015493949293909183019060ff1660058111156130a0576130a0615411565b60058111156130b1576130b1615411565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b8604161515606080880191909152600160701b86048516608080890191909152600160b01b909604831660a09788015287518a52878101519092168984015294860151831690880152938201511515868401526000968752600e909352942054600160801b90041692820192909252919050565b828411156131a65760405162461bcd60e51b815260206004820152600f60248201526e4d494e5f4d41585f5245564552534560881b6044820152606401610c3a565b8115806131bf5750846131bb578382106131bf565b8282115b6131f65760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b6044820152606401610c3a565b80158061320f57508461320b5782811161320f565b8381105b611c0d5760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b6044820152606401610c3a565b600080613252846113e4565b905061326085858584612538565b6000818152600c60205260408120805492945091600160b01b900463ffffffff1690036133ae578054600180830180546001600160a01b0319166001600160a01b038981169182179092559089166001600160b01b031990931692909217600160a01b61ffff8816021763ffffffff60b01b1916600160b01b63ffffffff86169081029190911784556000838152601560209081526040808320805463ffffffff19169094179093556016815282822080549485018155808352818320909401889055925493815260178352818120878252909252902055827f487ea6416487448c3ce943d750c8f67a275e4d8f26ac4093803bf63354b7006f826040516133a5919081546001600160a01b03808216835260a082901c61ffff16602084015260b09190911c63ffffffff166040830152600190920154909116606082015260800190565b60405180910390a25b50935093915050565b80156111fb576040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015613404573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613428919061586e565b905061343f6001600160a01b0385168430856142a5565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa919061586e565b9050826134b78383615990565b14611c0d5760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b6044820152606401610c3a565b6001600160a01b03811660009081526016602052604090205460010361134b57601380546001810182557f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0900180546001600160a01b0319166001600160a01b039390931692831790555460009182526014602052604090912055565b6001600160a01b0383166000908152600960205260408120818460038111156135a3576135a3615411565b60038111156135b4576135b4615411565b8152602001908152602001600020549050600060096000866001600160a01b03166001600160a01b03168152602001908152602001600020600085600381111561360057613600615411565b600381111561361157613611615411565b81526020810191909152604001600020556136366001600160a01b038516838361430c565b816001600160a01b031683600381111561365257613652615411565b856001600160a01b03167f0e80b333c403be7cb491b3ba7f29fe30014c594adbcbec04272291b2f72f6e6a8460405161368d91815260200190565b60405180910390a450505050565b6000848152600f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811683860152600160801b8204811683850152600160c01b909104166060820152878452600d8352818420825160e0810190935280548352600181015491949390919083019060ff16600581111561372457613724615411565b600581111561373557613735615411565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a09091015280519091506137b55760405162461bcd60e51b8152600401610c3a90615941565b6000868152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff16838701819052600160b01b90920463ffffffff1683860152600190930154909216606082015290845260089092529091205460ff161561383a5760405162461bcd60e51b8152600401610c3a90615748565b85600581111561384c5761384c615411565b8260200151600581111561386257613862615411565b1461387f5760405162461bcd60e51b8152600401610c3a9061596b565b600186600581111561389357613893615411565b036139375782516001600160401b03808716911611806138c85750846001600160401b031683602001516001600160401b0316105b15613932576040516001600160401b038616815287907f82c058420d58fdfcaa301ef645c860145096603267b7b7ac02831312ac2ab4479060200160405180910390a261392a8782600001518360600151856000015186606001518930613e40565b505050612e0f565b6139bd565b600286600581111561394b5761394b615411565b0361169a5782516001600160401b038087169116118015906139835750846001600160401b031683602001516001600160401b031610155b6139325760405162461bcd60e51b815260206004820152600b60248201526a50524943455f52414e474560a81b6044820152606401610c3a565b80516001600160a01b039081166000908152600b60205260408120546060850151608086015191909316926139f7918b9185918b8a61433d565b9050816001600160a01b03166352713f678a85606001518660200151886000015189606001518a6080015188604001518f6040518963ffffffff1660e01b8152600401613a9d9897969594939291909788526001600160a01b0396909616602088015261ffff949094166040870152606086019290925263ffffffff166080850152151560a08401526001600160401b0390811660c08401521660e08201526101000190565b60408051808303816000875af1925050508015613ad7575060408051601f3d908101601f19168201909252613ad4918101906159a3565b60015b613bdb57613ae36159c7565b806308c379a003613b1c5750613af76159e2565b80613b025750613b1e565b8060405162461bcd60e51b8152600401610c3a919061526f565b505b3d808015613b48576040519150601f19603f3d011682016040523d82523d6000602084013e613b4d565b606091505b50632eb752bf60e21b613b5f82615a6b565b6001600160e01b0319160361038e57602481015160448201516040518c907ff2c847d05971bf83dd347e0732c1ef893111318fb2540f5fe6f9783cb8d6ae5b90613bac9085908590615aa2565b60405180910390a2613bd38c876000015188606001518a600001518b606001518e30613e40565b505050613d24565b60008b8152600d602090815260408083206001810180546001600160401b038f16600160701b0267ffffffffffffffff60701b19909116179055895160109093529220558651613c2c908490615990565b8155600180820180546001600160401b0342166101000268ffffffffffffffffff199091161760031790558651613c6f918e9190613c6a8688615990565b6146c0565b85516001600160a01b038082166000908152600a6020526040902054613c9792911684614774565b60008c8152600f60205260408082209190915584810151606086015191518e927fdd0164525ce1bb6897fbd7000a7d93633016a05f498d94903ca1fcc7911cdf8192613d18928f9290899089906001600160401b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60405180910390a25050505b505050505050505050565b6000828152600d6020526040902054613d5a5760405162461bcd60e51b8152600401610c3a90615941565b6000828152600f60205260408120556001816001811115613d7d57613d7d615411565b03611bb35760046000838152600d602052604090206001015460ff166005811115613daa57613daa615411565b14613dc75760405162461bcd60e51b8152600401610c3a9061596b565b6000828152600d6020908152604080832060010180546001600160401b0342166101000268ffffffffffffffffff19909116176003179055519182526001600160a01b0385169184917f2cb817145129b5c52a6dc17e0605285c54d9c258fbf0a21e78bfff4e00813333910160405180910390a3505050565b6000878152600d6020908152604080832083815560010180546001600160d01b0319169055600f9091528120819055613e88613e828663ffffffff871661478e565b846147a6565b9050613e9788886003846146c0565b613ea0866147b6565b613eaa8689614a26565b6000613eb68287615990565b9050613ec3888883614774565b826001600160a01b0316897f0732bc6c415e7a220efee5f866e1e91a1335745b97373898ffecfddbc708a3e784604051613eff91815260200190565b60405180910390a3505050505050505050565b6000838152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff1695830195909552600160b01b900463ffffffff16928101929092526001015490911660608201528190819081613f7a8861303c565b8051909150613f9b5760405162461bcd60e51b8152600401610c3a90615941565b600080600080613fae8c87878e8e614b51565b93509350935093508460000151831115614030578451600090620186a0613fd58287615990565b613fdf91906158e4565b613fe99190615911565b905060075481111561402e5760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d41493d1925560921b6044820152606401610c3a565b505b819750829850809650846000015184111561408d5760405162461bcd60e51b815260206004820152601e60248201527f434c4f53455f4645455f4c41524745525f5448414e5f504f534954494f4e00006044820152606401610c3a565b61409e8c87600001516002876146c0565b6140ab86606001516147b6565b6140b986606001518d614a26565b60008c8152600d6020908152604080832083815560010180546001600160d01b0319169055600e825280832083905560109091528120556060860151865186516141079291908c9088614c03565b50505050505093509350939050565b60006001600160401b038316158061414057508560070b61413a8787868689614d6c565b60070b12155b156141dc576000620186a0856001600160401b03166064896001600160401b0316896001600160401b031661417591906158e4565b61417f91906158e4565b6141899190615911565b6141939190615911565b9050826141ca57856001600160401b0316816001600160401b031611156141bb5760006141d4565b6141c58187615ac0565b6141d4565b6141d48187615ae0565b9150506141df565b50815b95945050505050565b60006001600160401b038316158061421d575060065461420a90600019615b00565b6142178787868689614d6c565b60070b13155b156141dc576000620186a0856001600160401b03166064600654896001600160401b031661424b91906158e4565b61425591906158e4565b61425f9190615911565b6142699190615911565b90508261427a576141c58187615ae0565b856001600160401b0316816001600160401b0316111561429b5760006141d4565b6141d48187615ac0565b6040516001600160a01b038481166024830152838116604483015260648201839052612e0f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614df8565b6040516001600160a01b038381166024830152604482018390526111fb91859182169063a9059cbb906064016142da565b6040805160808101825260008082526020820181905291810182905260608101919091526000866001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143c5919061586e565b6000898152600e6020908152604091829020825160808101845290546001600160401b038082168352600160401b8204811693830193909352600160801b81048316938201849052600160c01b9004909116606082015293509091501580614438575060408301516001600160401b0316155b6144845760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f54505f444546494e4954494f4e530000000000000000006044820152606401610c3a565b60608201516001600160401b031615806144a9575060608301516001600160401b0316155b6144f55760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f534c5f444546494e4954494f4e530000000000000000006044820152606401610c3a565b60408301516001600160401b03161561456f57600061451f8585604001518963ffffffff16614e69565b90508561455557846001600160401b0316816001600160401b03161061454657600061455f565b6145508186615ac0565b61455f565b61455f8186615ae0565b6001600160401b03166040840152505b60608301516001600160401b0316156145e95760006145998585606001518963ffffffff16614e69565b9050856145af576145aa8186615ae0565b6145d9565b846001600160401b0316816001600160401b0316106145cf5760006145d9565b6145d98186615ac0565b6001600160401b03166060840152505b61460081858863ffffffff16856040015189614116565b6001600160401b03908116604084015242168252606082015161462f908290869063ffffffff8a1690896141e8565b6001600160401b0390811660608401908152428216602080860191825260009b8c52600e905260409a8b90208551815492519c87015193518516600160c01b026001600160c01b03948616600160801b02949094166001600160801b039d8616600160401b026001600160801b03199094169190951617919091179a909a1691909117179097559695505050505050565b8015612e0f576001600160a01b038316600090815260096020526040812082918460038111156146f2576146f2615411565b600381111561470357614703615411565b815260200190815260200160002060008282546147209190615b30565b90915550829050600381111561473857614738615411565b836001600160a01b0316857f52aab89a61b38ba21feecda2012e9c20aec817e5d709d0633c3fd693bb949cbb8460405161368d91815260200190565b80156111fb576111fb6001600160a01b038416838361430c565b6000606461479c83856158e4565b6114779190615911565b6000620186a061479c83856158e4565b6001600160a01b03811660009081526016602052604090205460010361134b576001600160a01b038116600090815260146020526040812054908190036148405760408051600080825260208201526001600160a01b038416917fd206397c5bb871d309f7602ac869a71536b264e19e25714421d6456b6b5008d991015b60405180910390a25050565b601361484d600183615990565b8154811061485d5761485d615b43565b6000918252602090912001546001600160a01b03838116911614614908576001600160a01b0382166000818152601460205260408120557fd206397c5bb871d309f7602ac869a71536b264e19e25714421d6456b6b5008d98260136148c3600183615990565b815481106148d3576148d3615b43565b60009182526020909120015460405161483492916001600160a01b0316909182526001600160a01b0316602082015260400190565b601354600110156149d6576013805461492390600190615990565b8154811061493357614933615b43565b6000918252602090912001546001600160a01b03166013614955600184615990565b8154811061496557614965615b43565b6000918252602082200180546001600160a01b0319166001600160a01b039390931692909217909155819060149060136149a0600185615990565b815481106149b0576149b0615b43565b60009182526020808320909101546001600160a01b031683528201929092526040019020555b6001600160a01b0382166000908152601460205260408120556013805480614a0057614a00615b59565b600082815260209020810160001990810180546001600160a01b03191690550190555050565b6001600160a01b038216600090815260176020908152604080832084845290915290205480156111fb576001600160a01b038316600090815260166020526040812090614a74600184615990565b8254909150614a8590600190615990565b811015614b015781546000908390614a9f90600190615990565b81548110614aaf57614aaf615b43565b9060005260206000200154905080838381548110614acf57614acf615b43565b60009182526020808320909101929092556001600160a01b038816815260178252604080822093825292909152208390555b81805480614b1157614b11615b59565b6000828152602080822083016000199081018390559092019092556001600160a01b03871682526017815260408083208784529091528120555050505050565b83516001600160a01b039081166000908152600b60209081526040808320546060890151928901519151630f1a62d160e31b8152939485948594859493909216926378d3168892614bad928e92908d908d908d90600401615b6f565b6080604051808303816000875af1158015614bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bf09190615bc6565b929c919b50995090975095505050505050565b6001600160a01b038085166000908152600a602052604081205490911690838510614cac57614c328385615990565b90506000614c408287615990565b6040516321d4911360e01b81526001600160a01b038a8116600483015260248201839052919250908416906321d4911390604401600060405180830381600087803b158015614c8e57600080fd5b505af1158015614ca2573d6000803e3d6000fd5b5050505050614d58565b50836000614cba8286615990565b905083811115614cdd57614cd88784614cd38785615990565b614774565b614d56565b6001600160a01b0383166321d4911330614cf78488615990565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015614d3d57600080fd5b505af1158015614d51573d6000803e3d6000fd5b505050505b505b614d63868883614774565b50505050505050565b6000858184614d8457614d7f8688615bfc565b614d8e565b614d8e8787615bfc565b905060008460070b620186a08360070b614da89190615b00565b614db29190615b00565b90506000600789900b614dc6606484615c2b565b614dd09190615c2b565b90508094508360070b8560070b13614de85784614dea565b835b9a9950505050505050505050565b600080602060008451602086016000885af180614e1b576040513d6000823e3d81fd5b50506000513d91508115614e33578060011415614e40565b6001600160a01b0384163b155b15612e0f57604051635274afe760e01b81526001600160a01b0385166004820152602401610c3a565b600080826001600160401b0316620186a06064866001600160401b0316886001600160401b0316614e9a91906158e4565b614ea491906158e4565b614eae9190615911565b6141df9190615911565b6003811061134b57600080fd5b606081018181106001600160401b0382111715614ef257634e487b7160e01b600052604160045260246000fd5b60405250565b61012081016001600160401b0381118282101715614ef257634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715614f5957634e487b7160e01b600052604160045260246000fd5b6040525050565b604051614f6c81614ef8565b90565b6001600160a01b038116811461134b57600080fd5b803561ffff81168114614f9657600080fd5b919050565b801515811461134b57600080fd5b8035614f9681614f9b565b803563ffffffff81168114614f9657600080fd5b80356001600160401b0381168114614f9657600080fd5b6000806000808486036101c0811215614ff757600080fd5b853561500281614eb8565b94506060601f198201121561501657600080fd5b60405161502281614ec5565b602087013561503081614f6f565b815261503e60408801614f84565b6020820152606087013561505181614f6f565b60408201529350610120607f19820181131561506c57600080fd5b615074614f60565b915061508260808801614fa9565b825260a0870135602083015261509a60c08801614fb4565b60408301526150ab60e08801614fc8565b60608301526101006150be818901614fc8565b60808401526150ce828901614fc8565b60a08401526150e06101408901614fc8565b60c08401526150f26101608901614fc8565b60e08401526151046101808901614fc8565b908301525091506151186101a08601614fb4565b905092959194509250565b60006020828403121561513557600080fd5b813561147781614f6f565b60006020828403121561515257600080fd5b5035919050565b6004811061134b57600080fd5b60008060006060848603121561517b57600080fd5b833561518681614f6f565b9250602084013561519681615159565b915060408401356151a681614f6f565b809150509250925092565b6000806000606084860312156151c657600080fd5b833592506151d660208501614fc8565b9150604084013590509250925092565b600080604083850312156151f957600080fd5b823561520481615159565b946020939093013593505050565b6000806040838503121561522557600080fd5b823561523081614f6f565b9150602083013561524081615159565b809150509250929050565b60005b8381101561526657818101518382015260200161524e565b50506000910152565b602081526000825180602084015261528e81604085016020870161524b565b601f01601f19169190910160400192915050565b600080604083850312156152b557600080fd5b823561520481614f6f565b6020808252825182820181905260009190848201906040850190845b818110156152f8578351835292840192918401916001016152dc565b50909695505050505050565b60008060006060848603121561531957600080fd5b8335925060208401356002811061532f57600080fd5b929592945050506040919091013590565b60008060006060848603121561535557600080fd5b83359250602084013561532f81614eb8565b6020808252825182820181905260009190848201906040850190845b818110156152f85783516001600160a01b031683529284019291840191600101615383565b600080600080608085870312156153be57600080fd5b8435935060208501356153d081615159565b92506153de60408601614fc8565b915061511860608601614fc8565b600080604083850312156153ff57600080fd5b82359150602083013561524081614f9b565b634e487b7160e01b600052602160045260246000fd5b6006811061543757615437615411565b9052565b87815260e0810161544f6020830189615427565b6001600160401b03968716604083015263ffffffff958616606083015293151560808201529190941660a08201529290911660c09092019190915292915050565b6000806000606084860312156154a557600080fd5b83356154b081614f6f565b95602085013595506040909401359392505050565b60a081016154d38288615427565b6001600160401b0395909516602082015261ffff939093166040840152901515606083015263ffffffff16608090910152919050565b600080600080600060a0868803121561552157600080fd5b8535945061553160208701614fc8565b935061553f60408701614fc8565b925061554d60608701614fc8565b915061555b60808701614fc8565b90509295509295909350565b60008060006060848603121561557c57600080fd5b833561558781614f6f565b9250602084013561519681614f6f565b600080600080608085870312156155ad57600080fd5b84356155b881614f6f565b935060208501356155c881614f6f565b92506155d660408601614f84565b915061511860608601614fb4565b600080600080608085870312156155fa57600080fd5b8435935060208501356153d081614eb8565b60008060006060848603121561562157600080fd5b8335925061563160208501614fc8565b915061563f60408501614fc8565b90509250925092565b60008060006060848603121561565d57600080fd5b833561566881614f6f565b9250602084013561532f81614f6f565b8051825263ffffffff602082015116602083015260408101511515604083015260608101516001600160401b03808216606085015280608084015116608085015250505050565b60a08101611c8e8284615678565b606081016156db8286615427565b6001600160401b039390931660208201526001600160a01b0391909116604090910152919050565b60006020828403121561571557600080fd5b815161147781614f9b565b6020808252600e908201526d08551c9859195c9cd41bdc9d185b60921b604082015260600190565b6020808252600b908201526a1410525497d4105554d15160aa1b604082015260600190565b6101e0810161577c8288615427565b63ffffffff808716602084015260018060a01b0380875116604085015261ffff6020880151166060850152806040880151166080850152508451151560a0840152602085015160c08401528060408601511660e08401525060608401516101006157f0818501836001600160401b03169052565b60808601516001600160401b0390811661012086015260a0870151811661014086015260c0870151811661016086015260e087015181166101808601529501519094166101a083015263ffffffff929092166101c090910152949350505050565b60006020828403121561586357600080fd5b815161147781614f6f565b60006020828403121561588057600080fd5b5051919050565b60208082526009908201526821547269676765727360b81b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b63ffffffff8181168382160190808211156158dd576158dd6158aa565b5092915050565b8082028115828204841417611c8e57611c8e6158aa565b634e487b7160e01b600052601260045260246000fd5b600082615920576159206158fb565b500490565b6000825161593781846020870161524b565b9190910192915050565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b6020808252600b908201526a57524f4e475f504841534560a81b604082015260600190565b81810381811115611c8e57611c8e6158aa565b600080604083850312156159b657600080fd5b505080516020909101519092909150565b600060033d1115614f6c5760046000803e5060005160e01c90565b600060443d10156159f05790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615a1f57505050505090565b8285019150815181811115615a375750505050505090565b843d8701016020828501011115615a515750505050505090565b615a6060208286010187614f26565b509095945050505050565b805160208201516001600160e01b03198082169291906004831015615a9a5780818460040360031b1b83161693505b505050919050565b6040810160128410615ab657615ab6615411565b9281526020015290565b6001600160401b038281168282160390808211156158dd576158dd6158aa565b6001600160401b038181168382160190808211156158dd576158dd6158aa565b80820260008212600160ff1b84141615615b1c57615b1c6158aa565b8181058314821517611c8e57611c8e6158aa565b80820180821115611c8e57611c8e6158aa565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b8681526001600160a01b038616602082015261ffff851660408201526101408101615b9d6060830186615678565b8361010083015260058310615bb457615bb4615411565b82610120830152979650505050505050565b60008060008060808587031215615bdc57600080fd5b505082516020840151604085015160609095015191969095509092509050565b600782810b9082900b03677fffffffffffffff198112677fffffffffffffff82131715611c8e57611c8e6158aa565b600082615c3a57615c3a6158fb565b600160ff1b821460001984141615615c5457615c546158aa565b50059056fea26469706673582212200017cff3e05517e4e014b901ae71b90fbffe8fbf395d4bab63441515ac24900064736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061038e5760003560e01c806382571409116101de578063b71f3cfe1161010f578063ece938cf116100ad578063f555f6971161007c578063f555f69714610aed578063f5f5ba7214610b0d578063f851a44014610b37578063f9b9484e14610b4a57600080fd5b8063ece938cf14610a5b578063ef6ecc5514610a64578063f2eb245e14610ac4578063f51f3fd314610ae457600080fd5b8063ddf474f1116100e9578063ddf474f1146109cd578063e640f33b14610a15578063eb48914014610a28578063ec7f8a3a14610a3b57600080fd5b8063b71f3cfe1461099c578063c07f9921146109a7578063ca3a3a82146109ba57600080fd5b806395be50501161017c578063a40d726811610156578063a40d726814610947578063aaf5eb681461095a578063acfd6b9214610969578063ad1f2b561461099457600080fd5b806395be5050146108a65780639ff69ffa14610921578063a2a25ea61461093457600080fd5b80638f7a8fb5116101b85780638f7a8fb5146107e257806390f24cac1461085d57806393a7f6a71461087057806394a1e6e51461089e57600080fd5b806382571409146107a657806386dc4975146107af5780638aa10435146107c257600080fd5b8063396f7b23116102c357806368f296a51161026157806376d901be1161023057806376d901be146107435780637b1039991461077657806380193b261461078957806380a7f3d41461079357600080fd5b806368f296a5146106c15780636e01af8d146106e7578063725b7d52146106fa57806374d8b78e1461071a57600080fd5b80634ebe5c331161029d5780634ebe5c33146105f35780635c60da1b14610606578063614d08f81461061957806366307a4f1461064657600080fd5b8063396f7b23146105ad5780633ad6f124146105c05780633b17a497146105d357600080fd5b80631ea9af6b1161033057806324b22a1f1161030a57806324b22a1f1461052c578063267822471461053f57806330d073d01461055257806338b903331461057d57600080fd5b80631ea9af6b146104e95780632457bc3a146104fc5780632485f3f11461050457600080fd5b8063135e563d1161036c578063135e563d1461048557806318fa4714146104985780631961aba0146104ad5780631d504dc6146104d657600080fd5b8063010570851461039357806303b90a87146103b9578063042e37c5146103fa575b600080fd5b6103a66103a1366004614fdf565b610bac565b6040519081526020015b60405180910390f35b6103e26103c7366004615123565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103b0565b610449610408366004615140565b600c60205260009081526040902080546001909101546001600160a01b0380831692600160a01b810461ffff1692600160b01b90910463ffffffff16911684565b604080516001600160a01b03958616815261ffff909416602085015263ffffffff909216918301919091529190911660608201526080016103b0565b6103e2610493366004615140565b611107565b6104ab6104a6366004615166565b611131565b005b6103a66104bb366004615123565b6001600160a01b031660009081526016602052604090205490565b6104ab6104e4366004615123565b611200565b6104ab6104f73660046151b1565b61134e565b6013546103a6565b610517610512366004615123565b6113e4565b60405163ffffffff90911681526020016103b0565b6104ab61053a3660046151e6565b61147e565b6001546103e2906001600160a01b031681565b6103a6610560366004615212565b600960209081526000928352604080842090915290825290205481565b6105a0604051806040016040528060048152602001630c4c0c4d60e21b81525081565b6040516103b0919061526f565b6003546103e2906001600160a01b031681565b6103a66105ce3660046152a2565b61171d565b6105e66105e1366004615123565b61174e565b6040516103b091906152c0565b6104ab610601366004615304565b6117ba565b6002546103e2906001600160a01b031681565b6105a06040518060400160405280600e81526020016d54726164696e67466c6f6f72563160901b81525081565b61068e610654366004615140565b600e602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b03958616815293851660208501529184169183019190915290911660608201526080016103b0565b6105176106cf366004615123565b60156020526000908152604090205463ffffffff1681565b6104ab6106f5366004615340565b61187e565b61070d6107083660046152a2565b611c14565b6040516103b09190615367565b6103e2610728366004615123565b600a602052600090815260409020546001600160a01b031681565b610766610751366004615140565b60086020526000908152604090205460ff1681565b60405190151581526020016103b0565b6004546103e2906001600160a01b031681565b6103a6620186a081565b6104ab6107a13660046153a8565b611c94565b6103a660075481565b6104ab6107bd3660046153ec565b6120e6565b6040805180820190915260048152630c4c0c4d60e21b60208201526105a0565b61084a6107f0366004615140565b600d602052600090815260409020805460019091015460ff808216916001600160401b03610100820481169263ffffffff600160481b8404811693600160681b810490921692600160701b83041691600160b01b90041687565b6040516103b0979695949392919061543b565b6103e261086b366004615490565b612179565b61076661087e366004615123565b6001600160a01b039081166000908152600a602052604090205416151590565b6103a66121be565b6109106108b4366004615140565b6000908152600d6020818152604080842060010154600c835293205491905260ff8083169361010084046001600160401b031693600160a01b90930461ffff1692600160681b810490921691600160b01b900463ffffffff1690565b6040516103b09594939291906154c5565b6104ab61092f366004615509565b6121cf565b6104ab610942366004615567565b612416565b6103a6610955366004615597565b612538565b6103a6670de0b6b3a764000081565b6103a66109773660046152a2565b601760209081526000928352604080842090915290825290205481565b6103a6606481565b6103a6633b9aca0081565b6104ab6109b53660046155e4565b6125a7565b6104ab6109c836600461560c565b612c64565b61068e6109db366004615140565b600f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b6104ab610a2336600461560c565b612e15565b6104ab610a363660046151b1565b612fa6565b6103a6610a49366004615123565b60146020526000908152604090205481565b6103a660055481565b610aa7610a72366004615648565b601260209081526000938452604080852082529284528284209052825290205463ffffffff8082169164010000000090041682565b6040805163ffffffff9384168152929091166020830152016103b0565b6103a6610ad2366004615140565b60106020526000908152604090205481565b6103a660065481565b610b00610afb366004615140565b61303c565b6040516103b091906156bf565b60408051808201909152600e81526d54726164696e67466c6f6f72563160901b60208201526105a0565b6000546103e2906001600160a01b031681565b610b9d610b58366004615140565b6000908152600d60209081526040808320600190810154600c90935292209091015460ff8216926101009092046001600160401b0316916001600160a01b0390911690565b6040516103b0939291906156cd565b6004805460405163731aa5f960e01b815233928101929092526000916001600160a01b039091169063731aa5f990602401602060405180830381865afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1e9190615703565b610c435760405162461bcd60e51b8152600401610c3a90615720565b60405180910390fd5b610c6b84604001516001600160a01b039081166000908152600a602052604090205416151590565b610cb75760405162461bcd60e51b815260206004820152601e60248201527f4e4f4e5f535550504f525445445f534554544c454d454e545f415353455400006044820152606401610c3a565b60208085015161ffff1660009081526008909152604090205460ff1615610cf05760405162461bcd60e51b8152600401610c3a90615748565b6001856002811115610d0457610d04615411565b1480610d2157506002856002811115610d1f57610d1f615411565b145b610d665760405162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f4f524445525f5459504560501b6044820152606401610c3a565b610dab836000015184606001516001600160401b031685608001516001600160401b03168660a001516001600160401b03168760c001516001600160401b0316613164565b60055484516001600160a01b031660009081526016602052604090205410610e0d5760405162461bcd60e51b815260206004820152601560248201527426a0ac2faa2920a222a9afa822a92faa2920a222a960591b6044820152606401610c3a565b6000610e26856040015186600001518760200151613246565b8092508193505050610e458560400151866000015186602001516133b7565b8451610e50906134fc565b6000828152600d60205260409020805415610e975760405162461bcd60e51b8152602060048201526007602482015266125117d554d15160ca1b6044820152606401610c3a565b600180820180548751604089015163ffffffff908116600160481b026cffffffff00000000000000000019921515600160681b0260ff60681b19928b16600160b01b02929092166cffffffff0000000000000000ff60681b1990941693909317171617905560208601518255600090886002811115610f1857610f18615411565b14610f24576002610f27565b60015b9050808260010160006101000a81548160ff02191690836005811115610f4f57610f4f615411565b0217905550428260010160016101000a8154816001600160401b0302191690836001600160401b031602179055506000600e600086815260200190815260200160002090508660a001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508660c001518160000160186101000a8154816001600160401b0302191690836001600160401b031602179055506000600f6000878152602001908152602001600020905087606001518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555087608001518160000160086101000a8154816001600160401b0302191690836001600160401b031602179055508760e001518160000160106101000a8154816001600160401b0302191690836001600160401b031602179055508761010001518160000160186101000a8154816001600160401b0302191690836001600160401b03160217905550857f835de04f5a930b169d6564c8f1c5f91f89abd9ea026b7488c94452abb900cc7484878c8c8c6040516110f295949392919061576d565b60405180910390a25050505050949350505050565b6013818154811061111757600080fd5b6000918252602090912001546001600160a01b0316905081565b6004805460405163a8e36e5b60e01b81526001600160a01b038681169382019390935291169063a8e36e5b90602401602060405180830381865afa15801561117d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a19190615851565b6001600160a01b0316336001600160a01b0316146111f05760405162461bcd60e51b815260206004820152600c60248201526b10a332b2b9a6b0b730b3b2b960a11b6044820152606401610c3a565b6111fb838383613578565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561123e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112629190615851565b6001600160a01b0316336001600160a01b0316146112b15760405162461bcd60e51b815260206004820152600c60248201526b10b83937bc3c9730b236b4b760a11b6044820152606401610c3a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af11580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061586e565b1561134b5760405162461bcd60e51b8152600401610c3a9060208082526004908201526319985a5b60e21b604082015260600190565b50565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb9190615703565b6113d75760405162461bcd60e51b8152600401610c3a90615887565b6111fb836002848461369b565b6001600160a01b03811660009081526015602052604081205463ffffffff9081169081106114545760405162461bcd60e51b815260206004820152601760248201527f504f534954494f4e5f494e4445585f4f564552464c4f570000000000000000006044820152606401610c3a565b600b8163ffffffff16101561146c5750600b92915050565b6114778160016158c0565b9392505050565b6000546001600160a01b031633146114c55760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b6044820152606401610c3a565b600081116115065760405162461bcd60e51b815260206004820152600e60248201526d43414e4e4f545f42455f5a45524f60901b6044820152606401610c3a565b6060600183600381111561151c5761151c615411565b03611555575060408051808201909152601281527136b0bc2a3930b232b9a832b92a3930b232b960711b602082015260058290556116d0565b600283600381111561156957611569615411565b036115f857606461157e620186a060326158e4565b6115889190615911565b8210156115d15760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b6044820152606401610c3a565b506040805180820190915260068082526536b0bc29b62360d11b60208301528290556116d0565b600383600381111561160c5761160c615411565b0361169a5761161f620186a060026158e4565b8210156116685760405162461bcd60e51b81526020600482015260176024820152762a2920a222afa820a920a6afa922a9aa2924a1aa24a7a760491b6044820152606401610c3a565b5060408051808201909152601081526f36b0bc29b0b734ba3ca83937b334ba2360811b602082015260078290556116d0565b60405162461bcd60e51b815260206004820152600b60248201526a155394d5541413d495115160aa1b6044820152606401610c3a565b806040516116de9190615925565b604051908190038120838252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab9060200160405180910390a2505050565b6016602052816000526040600020818154811061173957600080fd5b90600052602060002001600091509150505481565b6001600160a01b0381166000908152601660209081526040918290208054835181840281018401909452808452606093928301828280156117ae57602002820191906000526020600020905b81548152602001906001019080831161179a575b50505050509050919050565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615703565b6118735760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c5472696767657273290000000000006044820152606401610c3a565b6111fb338484613d2f565b6004805460405163419a519360e01b815233928101929092526001600160a01b03169063419a519390602401602060405180830381865afa1580156118c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118eb9190615703565b6119375760405162461bcd60e51b815260206004820152601a60248201527f212854726164657273506f7274616c7c7c5472696767657273290000000000006044820152606401610c3a565b6119456064620186a0615911565b81111561198b5760405162461bcd60e51b81526020600482015260146024820152734645455f4652414354494f4e5f544f4f5f42494760601b6044820152606401610c3a565b6000838152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff1660058111156119ca576119ca615411565b60058111156119db576119db615411565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b86041615156060870152600160701b85049093166080860152600160b01b90930490921660a0909301929092526000878152600d9091522054909150611a725760405162461bcd60e51b8152600401610c3a90615941565b6000848152600c6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1694830194909452600160b01b900463ffffffff16938101939093526001908101549091166060830152846002811115611ae157611ae1615411565b03611b4357600182602001516005811115611afe57611afe615411565b14611b3e5760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa6a0a925a2aa2fa7a92222a960811b6044820152606401610c3a565b611bee565b6002846002811115611b5757611b57615411565b03611bb357600282602001516005811115611b7457611b74615411565b14611b3e5760405162461bcd60e51b815260206004820152600f60248201526e2727aa2fa624a6a4aa2fa7a92222a960891b6044820152606401610c3a565b60405162461bcd60e51b815260206004820152601060248201526f57524f4e475f4f524445525f5459504560801b6044820152606401610c3a565b611c0d8582600001518360600151856000015186606001518833613e40565b5050505050565b6001600160a01b0382166000908152601160209081526040808320848452825291829020805483518184028101840190945280845260609392830182828015611c8657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c68575b505050505090505b92915050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d019190615703565b611d1d5760405162461bcd60e51b8152600401610c3a90615887565b6000848152600d60209081526040808320815160e08101909252805482526001810154919290919083019060ff166005811115611d5c57611d5c615411565b6005811115611d6d57611d6d615411565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a0909101528051909150611ded5760405162461bcd60e51b8152600401610c3a90615941565b6000858152600e60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b90910490911660608201529080806002886003811115611e5c57611e5c615411565b03611eb9578460800151611e895783606001516001600160401b0316866001600160401b03161015611ea4565b83606001516001600160401b0316866001600160401b031611155b925050506001600160401b0384166002611f9e565b6001886003811115611ecd57611ecd615411565b03611f30578460800151611efa5783604001516001600160401b0316866001600160401b03161115611f15565b83604001516001600160401b0316866001600160401b031610155b925083604001516001600160401b0316915060019050611f9e565b6003886003811115611f4457611f44615411565b03611f60575060019150506001600160401b0384166003611f9e565b60405162461bcd60e51b81526020600482015260136024820152722ba927a723afa624a6a4aa2faa2924a3a3a2a960691b6044820152606401610c3a565b82611fdb5760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b6044820152606401610c3a565b6000806000611feb8c8686613f12565b91945092509050600384600481111561200657612006615411565b036120735787608001516120265780896001600160401b03161015612034565b80896001600160401b031611155b9550856120735760405162461bcd60e51b815260206004820152600d60248201526c2320a629a2afaa2924a3a3a2a960991b6044820152606401610c3a565b8a600381111561208557612085615411565b604080516001600160401b038c16815260208101849052908101859052606081018490528d907fe67823c5c7b61d690bab4b46031d192b68f898b47bdf7daffbddff8e24aaf9bd9060800160405180910390a3505050505050505050505050565b6000546001600160a01b0316331461212d5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa0a226a4a760b11b6044820152606401610c3a565b600082815260086020526040808220805460ff19168415159081179091559051909184917f996384f9c771a575699aadc5e543fb849613b350a1b29584a1ecca98d2cfc1709190a35050565b601160205282600052604060002060205281600052604060002081815481106121a157600080fd5b6000918252602090912001546001600160a01b0316925083915050565b6121cc6064620186a0615911565b81565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223c9190615703565b6122585760405162461bcd60e51b8152600401610c3a90615720565b6000858152600d602052604090206002600182015460ff16600581111561228157612281615411565b1461229e5760405162461bcd60e51b8152600401610c3a9061596b565b6000868152600c6020908152604080832054600160a01b900461ffff168352600890915290205460ff16156122e55760405162461bcd60e51b8152600401610c3a90615748565b61232781600101600d9054906101000a900460ff16866001600160401b0316866001600160401b0316866001600160401b0316866001600160401b0316613164565b60018101805468ffffffffffffffff001916610100426001600160401b0390811691909102919091179091556000878152600e6020908152604080832080546001600160801b0316600160801b8987169081026001600160c01b031691909117600160c01b898816908102919091178355600f85529483902080548c88166001600160801b03199091168117600160401b988d169889021782558451928352948201959095529182019290925260608101939093529188907f098a3c0f7acdf2c147440d705e162d395db886273731a238b250793cde346d859060800160405180910390a25050505050505050565b6004546001600160a01b0316331461245c5760405162461bcd60e51b815260206004820152600960248201526821526567697374727960b81b6044820152606401610c3a565b6001600160a01b038381166000908152600a602052604090205416156124c45760405162461bcd60e51b815260206004820152601760248201527f41535345545f414c52454144595f535550504f525445440000000000000000006044820152606401610c3a565b6001600160a01b038084166000818152600a6020908152604080832080548689166001600160a01b03199182168117909255600b9093528184208054968816969093168617909255519092917fe34fb4592f12d191480ae66f1051ba82ee53c518b07f632579da8d40a74c77c891a4505050565b60408051606095861b6bffffffffffffffffffffffff199081166020808401919091529590961b909516603486015260f09290921b6001600160f01b031916604885015260e01b6001600160e01b031916604a8401528051602e818503018152604e9093019052815191012090565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126149190615703565b6126305760405162461bcd60e51b8152600401610c3a90615887565b6000848152600d60209081526040808320600e8352818420600c845293829020825160808101845281546001600160a01b038082168352600160a01b820461ffff1696830196909652600160b01b900463ffffffff169381019390935260010154909216606082015281549192916126ba5760405162461bcd60e51b8152600401610c3a90615941565b6003600184015460ff1660058111156126d5576126d5615411565b146126f25760405162461bcd60e51b8152600401610c3a9061596b565b80516001600160a01b039081166000908152600b60205260408120549091169080600189600281111561272757612727615411565b036129e25760006127c8846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612793919061586e565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff16614116565b9050886001600160401b0316816001600160401b03161461281d5760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b6044820152606401610c3a565b85546001600160401b03600160801b90910481169082160361286b5760405162461bcd60e51b8152602060048201526007602482015266053414d455f54560cc1b6044820152606401610c3a565b8092508560000160189054906101000a90046001600160401b03169150428660000160006101000a8154816001600160401b0302191690836001600160401b03160217905550836001600160a01b0316633cdc20f88c876060015188602001518b600001548c60010160099054906101000a900463ffffffff168d600101600d9054906101000a900460ff168e600101600e9054906101000a90046001600160401b03168e60000160109054906101000a90046001600160401b03168c6040518a63ffffffff1660e01b81526004016129aa999897969594939291909889526001600160a01b0397909716602089015261ffff959095166040880152606087019390935263ffffffff919091166080860152151560a08501526001600160401b0390811660c085015290811660e0840152166101008201526101200190565b600060405180830381600087803b1580156129c457600080fd5b505af11580156129d8573d6000803e3d6000fd5b5050505050612b73565b60028960028111156129f6576129f6615411565b0361169a576000612a97846001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061586e565b6001890154600160701b81046001600160401b031690600160481b810463ffffffff16908d90600160681b900460ff166141e8565b9050886001600160401b0316816001600160401b031614612aec5760405162461bcd60e51b815260206004820152600f60248201526e4241445f4649454c445f56414c554560881b6044820152606401610c3a565b85546001600160401b03600160c01b909104811690821603612b3a5760405162461bcd60e51b815260206004820152600760248201526614d0535157d4d360ca1b6044820152606401610c3a565b8554426001600160401b03908116600160401b026fffffffffffffffff0000000000000000198316178855600160801b90910416925090505b6001860154612b9f90600160681b900460ff166001600160401b03898116908190868116908616613164565b84546001600160401b03838116600160801b0267ffffffffffffffff60801b19918416600160c01b02919091166001600160801b0390921691909117178555886002811115612bf057612bf0615411565b846020015161ffff168b7f90bbb7e2b715065bd66ba75a34fca9b65694d5e75327dd0873a5e3e68837766789600101600d9054906101000a900460ff168c604051612c5092919091151582526001600160401b0316602082015260400190565b60405180910390a450505050505050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd19190615703565b612ced5760405162461bcd60e51b8152600401610c3a90615887565b6000838152600f6020908152604091829020825160808101845290546001600160401b038082168352600160401b82048116938301849052600160801b8204811694830194909452600160c01b90049092166060830152612d605760405162461bcd60e51b8152600401610c3a90615941565b80516001600160401b0380841691161180612d905750816001600160401b031681602001516001600160401b0316105b15612da657612da130856001613d2f565b612e0f565b6000806000612dc087866001600160401b03166004613f12565b6040805182815260208101859052908101839052929550909350915087907f9912c2c8197504aea5a1b52b98eeae3f4aecabe190feebc292455c355d4297cb9060600160405180910390a25050505b50505050565b6004805460405163731aa5f960e01b815233928101929092526001600160a01b03169063731aa5f990602401602060405180830381865afa158015612e5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e829190615703565b612e9e5760405162461bcd60e51b8152600401610c3a90615720565b6000838152600d602052604090208054612eca5760405162461bcd60e51b8152600401610c3a90615941565b6003600182015460ff166005811115612ee557612ee5615411565b14612f025760405162461bcd60e51b8152600401610c3a9061596b565b6001810180546001600160401b034281166101000268ffffffffffffffffff19909216919091176004179091556000858152600f60209081526040918290208054868516600160401b81026001600160801b03199092169589169586179190911782558351948552918401919091529186917fb7bb5d6820a30953d2858e9c448319c4cebbc70c347961e25f1adfff46566689910160405180910390a25050505050565b6004805460405163a5a2ed3760e01b815233928101929092526001600160a01b03169063a5a2ed3790602401602060405180830381865afa158015612fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130139190615703565b61302f5760405162461bcd60e51b8152600401610c3a90615887565b6111fb836001848461369b565b6040805160a081018252600080825260208083018290528284018290526060830182905260808301829052848252600d8152838220845160e0810190955280548552600181015493949293909183019060ff1660058111156130a0576130a0615411565b60058111156130b1576130b1615411565b8152600191909101546001600160401b036101008204811660208085019190915263ffffffff600160481b8404811660408087019190915260ff600160681b8604161515606080880191909152600160701b86048516608080890191909152600160b01b909604831660a09788015287518a52878101519092168984015294860151831690880152938201511515868401526000968752600e909352942054600160801b90041692820192909252919050565b828411156131a65760405162461bcd60e51b815260206004820152600f60248201526e4d494e5f4d41585f5245564552534560881b6044820152606401610c3a565b8115806131bf5750846131bb578382106131bf565b8282115b6131f65760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b6044820152606401610c3a565b80158061320f57508461320b5782811161320f565b8381105b611c0d5760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b6044820152606401610c3a565b600080613252846113e4565b905061326085858584612538565b6000818152600c60205260408120805492945091600160b01b900463ffffffff1690036133ae578054600180830180546001600160a01b0319166001600160a01b038981169182179092559089166001600160b01b031990931692909217600160a01b61ffff8816021763ffffffff60b01b1916600160b01b63ffffffff86169081029190911784556000838152601560209081526040808320805463ffffffff19169094179093556016815282822080549485018155808352818320909401889055925493815260178352818120878252909252902055827f487ea6416487448c3ce943d750c8f67a275e4d8f26ac4093803bf63354b7006f826040516133a5919081546001600160a01b03808216835260a082901c61ffff16602084015260b09190911c63ffffffff166040830152600190920154909116606082015260800190565b60405180910390a25b50935093915050565b80156111fb576040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015613404573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613428919061586e565b905061343f6001600160a01b0385168430856142a5565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa919061586e565b9050826134b78383615990565b14611c0d5760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b6044820152606401610c3a565b6001600160a01b03811660009081526016602052604090205460010361134b57601380546001810182557f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0900180546001600160a01b0319166001600160a01b039390931692831790555460009182526014602052604090912055565b6001600160a01b0383166000908152600960205260408120818460038111156135a3576135a3615411565b60038111156135b4576135b4615411565b8152602001908152602001600020549050600060096000866001600160a01b03166001600160a01b03168152602001908152602001600020600085600381111561360057613600615411565b600381111561361157613611615411565b81526020810191909152604001600020556136366001600160a01b038516838361430c565b816001600160a01b031683600381111561365257613652615411565b856001600160a01b03167f0e80b333c403be7cb491b3ba7f29fe30014c594adbcbec04272291b2f72f6e6a8460405161368d91815260200190565b60405180910390a450505050565b6000848152600f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811683860152600160801b8204811683850152600160c01b909104166060820152878452600d8352818420825160e0810190935280548352600181015491949390919083019060ff16600581111561372457613724615411565b600581111561373557613735615411565b8152600191909101546001600160401b0361010082048116602084015263ffffffff600160481b83048116604085015260ff600160681b84041615156060850152600160701b83049091166080840152600160b01b9091041660a09091015280519091506137b55760405162461bcd60e51b8152600401610c3a90615941565b6000868152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff16838701819052600160b01b90920463ffffffff1683860152600190930154909216606082015290845260089092529091205460ff161561383a5760405162461bcd60e51b8152600401610c3a90615748565b85600581111561384c5761384c615411565b8260200151600581111561386257613862615411565b1461387f5760405162461bcd60e51b8152600401610c3a9061596b565b600186600581111561389357613893615411565b036139375782516001600160401b03808716911611806138c85750846001600160401b031683602001516001600160401b0316105b15613932576040516001600160401b038616815287907f82c058420d58fdfcaa301ef645c860145096603267b7b7ac02831312ac2ab4479060200160405180910390a261392a8782600001518360600151856000015186606001518930613e40565b505050612e0f565b6139bd565b600286600581111561394b5761394b615411565b0361169a5782516001600160401b038087169116118015906139835750846001600160401b031683602001516001600160401b031610155b6139325760405162461bcd60e51b815260206004820152600b60248201526a50524943455f52414e474560a81b6044820152606401610c3a565b80516001600160a01b039081166000908152600b60205260408120546060850151608086015191909316926139f7918b9185918b8a61433d565b9050816001600160a01b03166352713f678a85606001518660200151886000015189606001518a6080015188604001518f6040518963ffffffff1660e01b8152600401613a9d9897969594939291909788526001600160a01b0396909616602088015261ffff949094166040870152606086019290925263ffffffff166080850152151560a08401526001600160401b0390811660c08401521660e08201526101000190565b60408051808303816000875af1925050508015613ad7575060408051601f3d908101601f19168201909252613ad4918101906159a3565b60015b613bdb57613ae36159c7565b806308c379a003613b1c5750613af76159e2565b80613b025750613b1e565b8060405162461bcd60e51b8152600401610c3a919061526f565b505b3d808015613b48576040519150601f19603f3d011682016040523d82523d6000602084013e613b4d565b606091505b50632eb752bf60e21b613b5f82615a6b565b6001600160e01b0319160361038e57602481015160448201516040518c907ff2c847d05971bf83dd347e0732c1ef893111318fb2540f5fe6f9783cb8d6ae5b90613bac9085908590615aa2565b60405180910390a2613bd38c876000015188606001518a600001518b606001518e30613e40565b505050613d24565b60008b8152600d602090815260408083206001810180546001600160401b038f16600160701b0267ffffffffffffffff60701b19909116179055895160109093529220558651613c2c908490615990565b8155600180820180546001600160401b0342166101000268ffffffffffffffffff199091161760031790558651613c6f918e9190613c6a8688615990565b6146c0565b85516001600160a01b038082166000908152600a6020526040902054613c9792911684614774565b60008c8152600f60205260408082209190915584810151606086015191518e927fdd0164525ce1bb6897fbd7000a7d93633016a05f498d94903ca1fcc7911cdf8192613d18928f9290899089906001600160401b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60405180910390a25050505b505050505050505050565b6000828152600d6020526040902054613d5a5760405162461bcd60e51b8152600401610c3a90615941565b6000828152600f60205260408120556001816001811115613d7d57613d7d615411565b03611bb35760046000838152600d602052604090206001015460ff166005811115613daa57613daa615411565b14613dc75760405162461bcd60e51b8152600401610c3a9061596b565b6000828152600d6020908152604080832060010180546001600160401b0342166101000268ffffffffffffffffff19909116176003179055519182526001600160a01b0385169184917f2cb817145129b5c52a6dc17e0605285c54d9c258fbf0a21e78bfff4e00813333910160405180910390a3505050565b6000878152600d6020908152604080832083815560010180546001600160d01b0319169055600f9091528120819055613e88613e828663ffffffff871661478e565b846147a6565b9050613e9788886003846146c0565b613ea0866147b6565b613eaa8689614a26565b6000613eb68287615990565b9050613ec3888883614774565b826001600160a01b0316897f0732bc6c415e7a220efee5f866e1e91a1335745b97373898ffecfddbc708a3e784604051613eff91815260200190565b60405180910390a3505050505050505050565b6000838152600c60209081526040808320815160808101835281546001600160a01b038082168352600160a01b820461ffff1695830195909552600160b01b900463ffffffff16928101929092526001015490911660608201528190819081613f7a8861303c565b8051909150613f9b5760405162461bcd60e51b8152600401610c3a90615941565b600080600080613fae8c87878e8e614b51565b93509350935093508460000151831115614030578451600090620186a0613fd58287615990565b613fdf91906158e4565b613fe99190615911565b905060075481111561402e5760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d41493d1925560921b6044820152606401610c3a565b505b819750829850809650846000015184111561408d5760405162461bcd60e51b815260206004820152601e60248201527f434c4f53455f4645455f4c41524745525f5448414e5f504f534954494f4e00006044820152606401610c3a565b61409e8c87600001516002876146c0565b6140ab86606001516147b6565b6140b986606001518d614a26565b60008c8152600d6020908152604080832083815560010180546001600160d01b0319169055600e825280832083905560109091528120556060860151865186516141079291908c9088614c03565b50505050505093509350939050565b60006001600160401b038316158061414057508560070b61413a8787868689614d6c565b60070b12155b156141dc576000620186a0856001600160401b03166064896001600160401b0316896001600160401b031661417591906158e4565b61417f91906158e4565b6141899190615911565b6141939190615911565b9050826141ca57856001600160401b0316816001600160401b031611156141bb5760006141d4565b6141c58187615ac0565b6141d4565b6141d48187615ae0565b9150506141df565b50815b95945050505050565b60006001600160401b038316158061421d575060065461420a90600019615b00565b6142178787868689614d6c565b60070b13155b156141dc576000620186a0856001600160401b03166064600654896001600160401b031661424b91906158e4565b61425591906158e4565b61425f9190615911565b6142699190615911565b90508261427a576141c58187615ae0565b856001600160401b0316816001600160401b0316111561429b5760006141d4565b6141d48187615ac0565b6040516001600160a01b038481166024830152838116604483015260648201839052612e0f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614df8565b6040516001600160a01b038381166024830152604482018390526111fb91859182169063a9059cbb906064016142da565b6040805160808101825260008082526020820181905291810182905260608101919091526000866001600160a01b0316631cb92ed36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143c5919061586e565b6000898152600e6020908152604091829020825160808101845290546001600160401b038082168352600160401b8204811693830193909352600160801b81048316938201849052600160c01b9004909116606082015293509091501580614438575060408301516001600160401b0316155b6144845760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f54505f444546494e4954494f4e530000000000000000006044820152606401610c3a565b60608201516001600160401b031615806144a9575060608301516001600160401b0316155b6144f55760405162461bcd60e51b815260206004820152601760248201527f4d554c5449504c455f534c5f444546494e4954494f4e530000000000000000006044820152606401610c3a565b60408301516001600160401b03161561456f57600061451f8585604001518963ffffffff16614e69565b90508561455557846001600160401b0316816001600160401b03161061454657600061455f565b6145508186615ac0565b61455f565b61455f8186615ae0565b6001600160401b03166040840152505b60608301516001600160401b0316156145e95760006145998585606001518963ffffffff16614e69565b9050856145af576145aa8186615ae0565b6145d9565b846001600160401b0316816001600160401b0316106145cf5760006145d9565b6145d98186615ac0565b6001600160401b03166060840152505b61460081858863ffffffff16856040015189614116565b6001600160401b03908116604084015242168252606082015161462f908290869063ffffffff8a1690896141e8565b6001600160401b0390811660608401908152428216602080860191825260009b8c52600e905260409a8b90208551815492519c87015193518516600160c01b026001600160c01b03948616600160801b02949094166001600160801b039d8616600160401b026001600160801b03199094169190951617919091179a909a1691909117179097559695505050505050565b8015612e0f576001600160a01b038316600090815260096020526040812082918460038111156146f2576146f2615411565b600381111561470357614703615411565b815260200190815260200160002060008282546147209190615b30565b90915550829050600381111561473857614738615411565b836001600160a01b0316857f52aab89a61b38ba21feecda2012e9c20aec817e5d709d0633c3fd693bb949cbb8460405161368d91815260200190565b80156111fb576111fb6001600160a01b038416838361430c565b6000606461479c83856158e4565b6114779190615911565b6000620186a061479c83856158e4565b6001600160a01b03811660009081526016602052604090205460010361134b576001600160a01b038116600090815260146020526040812054908190036148405760408051600080825260208201526001600160a01b038416917fd206397c5bb871d309f7602ac869a71536b264e19e25714421d6456b6b5008d991015b60405180910390a25050565b601361484d600183615990565b8154811061485d5761485d615b43565b6000918252602090912001546001600160a01b03838116911614614908576001600160a01b0382166000818152601460205260408120557fd206397c5bb871d309f7602ac869a71536b264e19e25714421d6456b6b5008d98260136148c3600183615990565b815481106148d3576148d3615b43565b60009182526020909120015460405161483492916001600160a01b0316909182526001600160a01b0316602082015260400190565b601354600110156149d6576013805461492390600190615990565b8154811061493357614933615b43565b6000918252602090912001546001600160a01b03166013614955600184615990565b8154811061496557614965615b43565b6000918252602082200180546001600160a01b0319166001600160a01b039390931692909217909155819060149060136149a0600185615990565b815481106149b0576149b0615b43565b60009182526020808320909101546001600160a01b031683528201929092526040019020555b6001600160a01b0382166000908152601460205260408120556013805480614a0057614a00615b59565b600082815260209020810160001990810180546001600160a01b03191690550190555050565b6001600160a01b038216600090815260176020908152604080832084845290915290205480156111fb576001600160a01b038316600090815260166020526040812090614a74600184615990565b8254909150614a8590600190615990565b811015614b015781546000908390614a9f90600190615990565b81548110614aaf57614aaf615b43565b9060005260206000200154905080838381548110614acf57614acf615b43565b60009182526020808320909101929092556001600160a01b038816815260178252604080822093825292909152208390555b81805480614b1157614b11615b59565b6000828152602080822083016000199081018390559092019092556001600160a01b03871682526017815260408083208784529091528120555050505050565b83516001600160a01b039081166000908152600b60209081526040808320546060890151928901519151630f1a62d160e31b8152939485948594859493909216926378d3168892614bad928e92908d908d908d90600401615b6f565b6080604051808303816000875af1158015614bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bf09190615bc6565b929c919b50995090975095505050505050565b6001600160a01b038085166000908152600a602052604081205490911690838510614cac57614c328385615990565b90506000614c408287615990565b6040516321d4911360e01b81526001600160a01b038a8116600483015260248201839052919250908416906321d4911390604401600060405180830381600087803b158015614c8e57600080fd5b505af1158015614ca2573d6000803e3d6000fd5b5050505050614d58565b50836000614cba8286615990565b905083811115614cdd57614cd88784614cd38785615990565b614774565b614d56565b6001600160a01b0383166321d4911330614cf78488615990565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015614d3d57600080fd5b505af1158015614d51573d6000803e3d6000fd5b505050505b505b614d63868883614774565b50505050505050565b6000858184614d8457614d7f8688615bfc565b614d8e565b614d8e8787615bfc565b905060008460070b620186a08360070b614da89190615b00565b614db29190615b00565b90506000600789900b614dc6606484615c2b565b614dd09190615c2b565b90508094508360070b8560070b13614de85784614dea565b835b9a9950505050505050505050565b600080602060008451602086016000885af180614e1b576040513d6000823e3d81fd5b50506000513d91508115614e33578060011415614e40565b6001600160a01b0384163b155b15612e0f57604051635274afe760e01b81526001600160a01b0385166004820152602401610c3a565b600080826001600160401b0316620186a06064866001600160401b0316886001600160401b0316614e9a91906158e4565b614ea491906158e4565b614eae9190615911565b6141df9190615911565b6003811061134b57600080fd5b606081018181106001600160401b0382111715614ef257634e487b7160e01b600052604160045260246000fd5b60405250565b61012081016001600160401b0381118282101715614ef257634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715614f5957634e487b7160e01b600052604160045260246000fd5b6040525050565b604051614f6c81614ef8565b90565b6001600160a01b038116811461134b57600080fd5b803561ffff81168114614f9657600080fd5b919050565b801515811461134b57600080fd5b8035614f9681614f9b565b803563ffffffff81168114614f9657600080fd5b80356001600160401b0381168114614f9657600080fd5b6000806000808486036101c0811215614ff757600080fd5b853561500281614eb8565b94506060601f198201121561501657600080fd5b60405161502281614ec5565b602087013561503081614f6f565b815261503e60408801614f84565b6020820152606087013561505181614f6f565b60408201529350610120607f19820181131561506c57600080fd5b615074614f60565b915061508260808801614fa9565b825260a0870135602083015261509a60c08801614fb4565b60408301526150ab60e08801614fc8565b60608301526101006150be818901614fc8565b60808401526150ce828901614fc8565b60a08401526150e06101408901614fc8565b60c08401526150f26101608901614fc8565b60e08401526151046101808901614fc8565b908301525091506151186101a08601614fb4565b905092959194509250565b60006020828403121561513557600080fd5b813561147781614f6f565b60006020828403121561515257600080fd5b5035919050565b6004811061134b57600080fd5b60008060006060848603121561517b57600080fd5b833561518681614f6f565b9250602084013561519681615159565b915060408401356151a681614f6f565b809150509250925092565b6000806000606084860312156151c657600080fd5b833592506151d660208501614fc8565b9150604084013590509250925092565b600080604083850312156151f957600080fd5b823561520481615159565b946020939093013593505050565b6000806040838503121561522557600080fd5b823561523081614f6f565b9150602083013561524081615159565b809150509250929050565b60005b8381101561526657818101518382015260200161524e565b50506000910152565b602081526000825180602084015261528e81604085016020870161524b565b601f01601f19169190910160400192915050565b600080604083850312156152b557600080fd5b823561520481614f6f565b6020808252825182820181905260009190848201906040850190845b818110156152f8578351835292840192918401916001016152dc565b50909695505050505050565b60008060006060848603121561531957600080fd5b8335925060208401356002811061532f57600080fd5b929592945050506040919091013590565b60008060006060848603121561535557600080fd5b83359250602084013561532f81614eb8565b6020808252825182820181905260009190848201906040850190845b818110156152f85783516001600160a01b031683529284019291840191600101615383565b600080600080608085870312156153be57600080fd5b8435935060208501356153d081615159565b92506153de60408601614fc8565b915061511860608601614fc8565b600080604083850312156153ff57600080fd5b82359150602083013561524081614f9b565b634e487b7160e01b600052602160045260246000fd5b6006811061543757615437615411565b9052565b87815260e0810161544f6020830189615427565b6001600160401b03968716604083015263ffffffff958616606083015293151560808201529190941660a08201529290911660c09092019190915292915050565b6000806000606084860312156154a557600080fd5b83356154b081614f6f565b95602085013595506040909401359392505050565b60a081016154d38288615427565b6001600160401b0395909516602082015261ffff939093166040840152901515606083015263ffffffff16608090910152919050565b600080600080600060a0868803121561552157600080fd5b8535945061553160208701614fc8565b935061553f60408701614fc8565b925061554d60608701614fc8565b915061555b60808701614fc8565b90509295509295909350565b60008060006060848603121561557c57600080fd5b833561558781614f6f565b9250602084013561519681614f6f565b600080600080608085870312156155ad57600080fd5b84356155b881614f6f565b935060208501356155c881614f6f565b92506155d660408601614f84565b915061511860608601614fb4565b600080600080608085870312156155fa57600080fd5b8435935060208501356153d081614eb8565b60008060006060848603121561562157600080fd5b8335925061563160208501614fc8565b915061563f60408501614fc8565b90509250925092565b60008060006060848603121561565d57600080fd5b833561566881614f6f565b9250602084013561532f81614f6f565b8051825263ffffffff602082015116602083015260408101511515604083015260608101516001600160401b03808216606085015280608084015116608085015250505050565b60a08101611c8e8284615678565b606081016156db8286615427565b6001600160401b039390931660208201526001600160a01b0391909116604090910152919050565b60006020828403121561571557600080fd5b815161147781614f9b565b6020808252600e908201526d08551c9859195c9cd41bdc9d185b60921b604082015260600190565b6020808252600b908201526a1410525497d4105554d15160aa1b604082015260600190565b6101e0810161577c8288615427565b63ffffffff808716602084015260018060a01b0380875116604085015261ffff6020880151166060850152806040880151166080850152508451151560a0840152602085015160c08401528060408601511660e08401525060608401516101006157f0818501836001600160401b03169052565b60808601516001600160401b0390811661012086015260a0870151811661014086015260c0870151811661016086015260e087015181166101808601529501519094166101a083015263ffffffff929092166101c090910152949350505050565b60006020828403121561586357600080fd5b815161147781614f6f565b60006020828403121561588057600080fd5b5051919050565b60208082526009908201526821547269676765727360b81b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b63ffffffff8181168382160190808211156158dd576158dd6158aa565b5092915050565b8082028115828204841417611c8e57611c8e6158aa565b634e487b7160e01b600052601260045260246000fd5b600082615920576159206158fb565b500490565b6000825161593781846020870161524b565b9190910192915050565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b6020808252600b908201526a57524f4e475f504841534560a81b604082015260600190565b81810381811115611c8e57611c8e6158aa565b600080604083850312156159b657600080fd5b505080516020909101519092909150565b600060033d1115614f6c5760046000803e5060005160e01c90565b600060443d10156159f05790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615a1f57505050505090565b8285019150815181811115615a375750505050505090565b843d8701016020828501011115615a515750505050505090565b615a6060208286010187614f26565b509095945050505050565b805160208201516001600160e01b03198082169291906004831015615a9a5780818460040360031b1b83161693505b505050919050565b6040810160128410615ab657615ab6615411565b9281526020015290565b6001600160401b038281168282160390808211156158dd576158dd6158aa565b6001600160401b038181168382160190808211156158dd576158dd6158aa565b80820260008212600160ff1b84141615615b1c57615b1c6158aa565b8181058314821517611c8e57611c8e6158aa565b80820180821115611c8e57611c8e6158aa565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b8681526001600160a01b038616602082015261ffff851660408201526101408101615b9d6060830186615678565b8361010083015260058310615bb457615bb4615411565b82610120830152979650505050505050565b60008060008060808587031215615bdc57600080fd5b505082516020840151604085015160609095015191969095509092509050565b600782810b9082900b03677fffffffffffffff198112677fffffffffffffff82131715611c8e57611c8e6158aa565b600082615c3a57615c3a6158fb565b600160ff1b821460001984141615615c5457615c546158aa565b50059056fea26469706673582212200017cff3e05517e4e014b901ae71b90fbffe8fbf395d4bab63441515ac24900064736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.