Contract

0x6f6BFa4bf2Ce00D85382A4e3e15A0dD3E1B7D559

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Trigger_close Tr...10290382024-12-21 12:42:361 hr ago1734784956IN
0x6f6BFa4b...3E1B7D559
1 wei0.0071642210.3693
Trigger_open Tra...10162662024-12-21 10:27:344 hrs ago1734776854IN
0x6f6BFa4b...3E1B7D559
1 wei0.000962291.39285714
Trigger_close Tr...9918962024-12-21 5:48:178 hrs ago1734760097IN
0x6f6BFa4b...3E1B7D559
1 wei0.000623251
Trigger_open Tra...9413692024-12-20 22:53:3115 hrs ago1734735211IN
0x6f6BFa4b...3E1B7D559
1 wei0.000777611.074
Allow Trigger Ac...8857542024-12-20 14:13:0324 hrs ago1734703983IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857512024-12-20 14:13:0224 hrs ago1734703982IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857452024-12-20 14:13:0024 hrs ago1734703980IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857412024-12-20 14:12:5824 hrs ago1734703978IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857362024-12-20 14:12:5724 hrs ago1734703977IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857322024-12-20 14:12:5524 hrs ago1734703975IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857282024-12-20 14:12:5324 hrs ago1734703973IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857242024-12-20 14:12:5124 hrs ago1734703971IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857212024-12-20 14:12:5024 hrs ago1734703970IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857172024-12-20 14:12:4824 hrs ago1734703968IN
0x6f6BFa4b...3E1B7D559
0 S0.000082621.1
Allow Trigger Ac...8857122024-12-20 14:12:4724 hrs ago1734703967IN
0x6f6BFa4b...3E1B7D559
0 S0.000101431.1
Set Open Positio...8857072024-12-20 14:12:4524 hrs ago1734703965IN
0x6f6BFa4b...3E1B7D559
0 S0.000027921.1
Set Market Order...8857022024-12-20 14:12:4324 hrs ago1734703963IN
0x6f6BFa4b...3E1B7D559
0 S0.000027881.1
Set Max Triggers...8856982024-12-20 14:12:4224 hrs ago1734703962IN
0x6f6BFa4b...3E1B7D559
0 S0.000033231.1
Set Spread Fract...8856952024-12-20 14:12:4024 hrs ago1734703960IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856922024-12-20 14:12:3824 hrs ago1734703958IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856882024-12-20 14:12:3724 hrs ago1734703957IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856842024-12-20 14:12:3524 hrs ago1734703955IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856802024-12-20 14:12:3424 hrs ago1734703954IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856762024-12-20 14:12:3224 hrs ago1734703952IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
Set Spread Fract...8856712024-12-20 14:12:3024 hrs ago1734703950IN
0x6f6BFa4b...3E1B7D559
0 S0.000052411.1
View all transactions

Latest 4 internal transactions

Parent Transaction Hash Block From To
10290382024-12-21 12:42:361 hr ago1734784956
0x6f6BFa4b...3E1B7D559
1 wei
10162662024-12-21 10:27:344 hrs ago1734776854
0x6f6BFa4b...3E1B7D559
1 wei
9918962024-12-21 5:48:178 hrs ago1734760097
0x6f6BFa4b...3E1B7D559
1 wei
9413692024-12-20 22:53:3115 hrs ago1734735211
0x6f6BFa4b...3E1B7D559
1 wei
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TriggersV1

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 25 : TriggersV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../interfaces/IRegistryV1.sol";
import "../interfaces/ITradingFloorV1.sol";
import "../interfaces/IPriceValidatorV1.sol";
import "../interfaces/IOrderBookV1.sol";

import "../../AdministrationContracts/ClaimableAdmin.sol";

import "./TriggersPermissionBase.sol";
import "./ConfidenceChecker.sol";
import "./PriceAdjustmentBase.sol";
import "../Locks/SystemLocker.sol";

/**
 * @title TriggersV1
 * @dev The main contract for handling triggers and executing trade requests and limits triggering
 */
contract TriggersV1 is
  ClaimableAdmin,
  TriggersPermissionBase,
  ConfidenceChecker,
  PriceAdjustmentBase,
  SystemLocker
{
  // ***** Contracts (Immutable) *****

  ITradingFloorV1 public immutable tradingFloor;
  IOrderBookV1 public immutable orderBook;
  IPriceValidatorV1 public priceValidator;

  // ***** Trigger Params *****

  uint public minTriggerPeriodForMarketOrders = 3; // seconds
  uint public maxTriggerPeriodForMarketOrders = 60; // seconds

  uint public minTriggerPeriodForLimitOrders = 60; // seconds

  uint public marketOrdersTimeout = 60; // seconds e.g 30

  // @notice the range in which the market order can be accepted (range is [orderTimestamp, orderTimestamp + range] )
  uint public marketOrderTightTimeRange = 60 * 3; // 5 seconds

  // @notice the range in which a trigger reported price can accept(range is [blockTimestamp - triggerPriceFreshnessTimeRange, blockTimestamp] )
  uint public triggerPriceFreshnessTimeRange = 60 * 30; // 30 minutes

  uint public marketOrderCancelFeeFraction = (1 * FRACTION_SCALE) / 1000; // FRACTION_SCALE (0.001 = 0.01%)

  uint public openPositionCancellationFeeFraction = (2 * FRACTION_SCALE) / 1000; // FRACTION_SCALE (0.002 = 0.02%)

  uint public maxTriggersPerBlock = 3;

  mapping(uint => uint) public triggersPerBlock;

  // ***** Done/Pause state *****

  bool public isPaused; // Prevent opening new trades
  bool public isDone; // Prevent any interaction with the contract

  // ***** Events *****

  event PausedToggled(bool paused);
  event DoneToggled(bool done);

  event NumberUpdated(string indexed name, uint value);
  event AddressUpdated(string indexed name, address value);

  // Events
  event OpenPositionExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    TradingEnumsV1.PositionPhase indexed phase,
    uint triggerPrice,
    uint basePrice,
    uint priceTimestamp
  );

  event ClosePositionExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    TradingEnumsV1.PositionPhase indexed phase,
    uint triggerPrice,
    uint basePrice,
    uint priceTimestamp
  );

  event SlExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    uint16 indexed pairId,
    uint triggerPrice,
    uint basePrice,
    uint priceTimestamp
  );

  event TpExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    uint16 indexed pairId,
    uint triggerPrice,
    uint basePrice,
    uint priceTimestamp
  );

  event UpdatePositionSingleFieldExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    OrderBookStructsV1.UpdatePositionFieldOrderType indexed orderType,
    TradingEnumsV1.PositionField positionField,
    uint256 fieldValue,
    uint64 triggerPrice
  );

  event UpdatePositionSingleFieldRejected(
    address indexed triggerer,
    bytes32 indexed positionId,
    OrderBookStructsV1.UpdatePositionFieldOrderType indexed orderType,
    TradingEnumsV1.PositionField positionField,
    uint256 fieldValue,
    uint64 triggerPrice,
    string rejectionReason,
    uint256 rejectionValue
  );

  event LiquidationExecuted(
    address indexed triggerer,
    bytes32 indexed positionId,
    uint16 indexed pairId,
    uint triggerPrice,
    uint basePrice,
    uint priceTimestamp
  );

  event MarketOpenTimeoutTriggered(
    address indexed triggerer,
    bytes32 indexed positionId,
    uint16 indexed pairId
  );

  event MarketCloseTimeoutTriggered(
    address indexed triggerer,
    bytes32 indexed positionId,
    uint16 indexed pairId
  );

  event PositionUpdateTimeoutTriggered(
    address indexed triggerer,
    bytes32 indexed positionId,
    OrderBookStructsV1.UpdatePositionFieldOrderType indexed orderType,
    uint64 fieldValueA,
    uint64 fieldValueB
  );

  // ***** Modifiers *****

  modifier notDone() {
    require(!isDone, "DONE");
    _;
  }
  modifier notDoneOrPaused() {
    require(!isDone, "DONE");
    require(!isPaused, "PAUSED");
    _;
  }

  // ***** Views *****

  function getValidatedPrice(
    uint pairId,
    bytes[] calldata pricePayload
  ) public payable returns (IPriceValidatorV1.ValidatedPrice memory) {
    return
      validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );
  }

  // ***** Constructor *****

  constructor(
    ITradingFloorV1 _tradingFloor
  )
    ConfidenceChecker((FRACTION_SCALE * 10) / 100) // 10% max confidence
    PriceAdjustmentBase((FRACTION_SCALE * 1) / 100) // 1% max spread
    SystemLocker(_tradingFloor.registry())
  {
    require(address(_tradingFloor) != address(0), "WRONG_PARAMS");

    tradingFloor = _tradingFloor;
    orderBook = IOrderBookV1(IRegistryV1(_tradingFloor.registry()).orderBook());
  }

  // ***** Pause/Done (Admin) Toggles *****

  function togglePause() external onlyAdmin {
    isPaused = !isPaused;

    emit PausedToggled(isPaused);
  }

  function toggleDone() external onlyAdmin {
    isDone = !isDone;

    emit DoneToggled(isDone);
  }

  // ***** Admin functions *****

  function setPriceValidator(address _priceValidator) external onlyAdmin {
    // Sanity
    require(
      IPriceValidatorV1(_priceValidator).isPriceValidator(),
      "!PriceValidator"
    );

    // Setting
    priceValidator = IPriceValidatorV1(_priceValidator);
    emit AddressUpdated("PriceValidator", _priceValidator);
  }

  function allowTriggerAccount(address account) external onlyAdmin {
    allowTriggerAccountInternal(account);
  }

  function disallowTriggerAccount(address account) external onlyAdmin {
    disallowTriggerAccountInternal(account);
  }

  function setMaxConfidenceForPair(
    uint pairId,
    uint32 maxConfidenceFraction
  ) external onlyAdmin {
    setMaxConfidenceForPairInternal(pairId, maxConfidenceFraction);
  }

  function setSpreadFractionForPair(
    uint pairId,
    uint32 spreadFraction
  ) external onlyAdmin {
    setSpreadFractionForPairInternal(pairId, spreadFraction);
  }

  function setMinTriggerPeriodForMarketOrders(
    uint _minTriggerPeriodForMarketOrders
  ) external onlyAdmin {
    require(
      _minTriggerPeriodForMarketOrders < maxTriggerPeriodForMarketOrders,
      "WRONG_VALUE"
    );
    minTriggerPeriodForMarketOrders = _minTriggerPeriodForMarketOrders;
    emit NumberUpdated(
      "minTriggerPeriodForMarketOrders",
      _minTriggerPeriodForMarketOrders
    );
  }

  function setMaxTriggerPeriodForMarketOrders(
    uint _maxTriggerPeriodForMarketOrders
  ) external onlyAdmin {
    require(
      _maxTriggerPeriodForMarketOrders > minTriggerPeriodForMarketOrders,
      "WRONG_VALUE"
    );
    maxTriggerPeriodForMarketOrders = _maxTriggerPeriodForMarketOrders;
    emit NumberUpdated(
      "maxTriggerPeriodForMarketOrders",
      _maxTriggerPeriodForMarketOrders
    );
  }

  function setMinTriggerPeriodForLimitOrders(
    uint _minTriggerPeriodForLimitOrders
  ) external onlyAdmin {
    minTriggerPeriodForLimitOrders = _minTriggerPeriodForLimitOrders;
    emit NumberUpdated(
      "minTriggerPeriodForLimitOrders",
      _minTriggerPeriodForLimitOrders
    );
  }

  function setMarketOrdersTimeout(
    uint _marketOrdersTimeout
  ) external onlyAdmin {
    marketOrdersTimeout = _marketOrdersTimeout;
    emit NumberUpdated("marketOrdersTimeout", _marketOrdersTimeout);
  }

  function setMarketOrderTightTimeRange(
    uint _marketOrderTightTimeRange
  ) external onlyAdmin {
    marketOrderTightTimeRange = _marketOrderTightTimeRange;
    emit NumberUpdated("marketOrderTightTimeRange", _marketOrderTightTimeRange);
  }

  function setTriggerPriceFreshnessTimeRange(
    uint _triggerPriceFreshnessTimeRange
  ) external onlyAdmin {
    triggerPriceFreshnessTimeRange = _triggerPriceFreshnessTimeRange;
    emit NumberUpdated(
      "triggerPriceFreshnessTimeRange",
      _triggerPriceFreshnessTimeRange
    );
  }

  function setMarketOrderCancelFeeFraction(
    uint _marketOrderCancelFeeFraction
  ) external onlyAdmin {
    marketOrderCancelFeeFraction = _marketOrderCancelFeeFraction;
    emit NumberUpdated(
      "marketOrderCancelFeeFraction",
      _marketOrderCancelFeeFraction
    );
  }

  function setOpenPositionCancellationFeeFraction(
    uint _openPositionCancellationFeeFraction
  ) external onlyAdmin {
    openPositionCancellationFeeFraction = _openPositionCancellationFeeFraction;
    emit NumberUpdated(
      "openPositionCancellationFeeFraction",
      _openPositionCancellationFeeFraction
    );
  }

  function setMaxTriggersPerBlock(
    uint _maxTriggersPerBlock
  ) external onlyAdmin {
    maxTriggersPerBlock = _maxTriggersPerBlock;
    emit NumberUpdated("maxTriggersPerBlock", _maxTriggersPerBlock);
  }

  // ***** Open Position Triggers *****

  /**
   * Triggers a openTrade at market price.
   * @dev This function does not revert (as long as the price is valid and the pending order exists),
   *      in case of a failed condition for the trade order, The pending market order will be canceled.
   */
  function trigger_openTrade_market(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (
      TradingEnumsV1.PositionPhase phase,
      uint timestamp,
      uint16 pairId,
      bool long,
      uint32 spreadReductionF
    ) = tradingFloor.getPositionTriggerInfo(_positionId);

    require(timestamp > 0, "NO_PENDING_MARKET_ORDER");
    require(
      phase == TradingEnumsV1.PositionPhase.OPEN_MARKET,
      "NOT_OPEN_MARKET"
    );

    // ** Order price validity **
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // ** Market order timestamp validity **
    validateMarketOrderTimestampInternal(timestamp, validatedPrice.timestamp);

    uint64 priceAfterImpact = validatedPrice.price;

    uint64 triggerPrice = calculatePostSpreadPrice(
      pairId,
      priceAfterImpact,
      spreadReductionF,
      long
    );

    safelyIncreaseTriggersPerBlock();

    tradingFloor.openNewPosition_market(
      _positionId,
      triggerPrice,
      openPositionCancellationFeeFraction
    );

    emit OpenPositionExecuted(
      msg.sender,
      _positionId,
      phase,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  function trigger_openTrade_limit(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (
      TradingEnumsV1.PositionPhase phase,
      uint timestamp,
      uint16 pairId,
      bool long,
      uint32 spreadReductionF
    ) = tradingFloor.getPositionTriggerInfo(_positionId);

    require(timestamp > 0, "NO_PENDING_LIMIT_ORDER");
    require(phase == TradingEnumsV1.PositionPhase.OPEN_LIMIT, "NOT_OPEN_LIMIT");

    // Order price validity
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // Limit order timestamp validity
    validateLimitOrderTimestampInternal(timestamp, validatedPrice.timestamp);

    uint64 priceAfterImpact = validatedPrice.price;
    uint64 triggerPrice = calculatePostSpreadPrice(
      pairId,
      priceAfterImpact,
      spreadReductionF,
      long
    );

    safelyIncreaseTriggersPerBlock();

    tradingFloor.openNewPosition_limit(
      _positionId,
      triggerPrice,
      openPositionCancellationFeeFraction
    );

    emit OpenPositionExecuted(
      msg.sender,
      _positionId,
      phase,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  // ***** Close Position Triggers *****

  function trigger_closeTrade_market(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (
      TradingEnumsV1.PositionPhase phase,
      uint timestamp,
      uint16 pairId,
      ,

    ) = tradingFloor.getPositionTriggerInfo(_positionId);

    require(timestamp > 0, "NO_PENDING_MARKET_ORDER");
    require(
      phase == TradingEnumsV1.PositionPhase.CLOSE_MARKET,
      "NOT_CLOSE_MARKET"
    );

    // ** Market order price validity **
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // ** Market order timestamp validity **
    validateMarketOrderTimestampInternal(timestamp, validatedPrice.timestamp);

    uint64 priceAfterImpact = validatedPrice.price;
    uint64 triggerPrice = priceAfterImpact;

    safelyIncreaseTriggersPerBlock();

    tradingFloor.closeExistingPosition_Market(
      _positionId,
      validatedPrice.price,
      triggerPrice
    );

    emit ClosePositionExecuted(
      msg.sender,
      _positionId,
      phase,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  function trigger_closeTrade_SL(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);
    TradingFloorStructsV1.PositionLimitsInfo memory limitInfo = tradingFloor
      .positionLimitsInfoById(_positionId);
    require(pairId > 0, "NO_SUCH_POSITION");
    require(limitInfo.sl > 0, "NO_SL");

    uint slLastUpdated = limitInfo.slLastUpdated;

    // ** Price validity **
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    validateLimitOrderTimestampInternal(
      slLastUpdated,
      validatedPrice.timestamp
    );

    uint64 triggerPrice = validatedPrice.price;

    safelyIncreaseTriggersPerBlock();

    tradingFloor.closeExistingPosition_Limit(
      _positionId,
      TradingEnumsV1.LimitTrigger.SL,
      validatedPrice.price,
      triggerPrice
    );

    emit SlExecuted(
      msg.sender,
      _positionId,
      pairId,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  function trigger_closeTrade_TP(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);
    TradingFloorStructsV1.PositionLimitsInfo memory limitInfo = tradingFloor
      .positionLimitsInfoById(_positionId);
    require(pairId > 0, "NO_SUCH_POSITION");
    require(limitInfo.tp > 0, "NO_TP");

    uint tpLastUpdated = limitInfo.tpLastUpdated;

    // ** Price validity **
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    validateLimitOrderTimestampInternal(
      tpLastUpdated,
      validatedPrice.timestamp
    );

    uint64 triggerPrice = validatedPrice.price;

    //        if (t.buy) {
    //            require(finalPrice >= limitInfo.tp, "LONG_PRICE_LESS_THAN_TP");
    //        } else {
    //            require(finalPrice <= limitInfo.tp, "SHORT_PRICE_MORE_THAN_TP");
    //        }

    safelyIncreaseTriggersPerBlock();

    tradingFloor.closeExistingPosition_Limit(
      _positionId,
      TradingEnumsV1.LimitTrigger.TP,
      validatedPrice.price,
      triggerPrice
    );

    emit TpExecuted(
      msg.sender,
      _positionId,
      pairId,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  function trigger_closeTrade_LIQ(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);
    require(pairId > 0, "NO_SUCH_POSITION");

    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    uint64 triggerPrice = validatedPrice.price;

    safelyIncreaseTriggersPerBlock();

    tradingFloor.closeExistingPosition_Limit(
      _positionId,
      TradingEnumsV1.LimitTrigger.LIQ,
      validatedPrice.price,
      triggerPrice
    );

    emit LiquidationExecuted(
      msg.sender,
      _positionId,
      pairId,
      triggerPrice,
      validatedPrice.price,
      validatedPrice.timestamp
    );
  }

  // ***** Update Position Triggers *****

  function trigger_update_TP(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    OrderBookStructsV1.UpdatePositionFieldOrder memory o = orderBook
      .readAndDeleteUpdatePositionOrder(_positionId);

    require(
      o.orderType == OrderBookStructsV1.UpdatePositionFieldOrderType.UPDATE_TP,
      "UPDATE_ORDER_NOT_TP"
    );

    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);

    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // ** Market order timestamp validity **
    validateMarketOrderTimestampInternal(o.timestamp, validatedPrice.timestamp);

    safelyIncreaseTriggersPerBlock();

    uint64 triggerPrice = validatedPrice.price;

    safePositionSingleFieldUpdateInternal(
      msg.sender,
      _positionId,
      o.orderType,
      TradingEnumsV1.PositionField.TP,
      o.fieldValueA,
      triggerPrice
    );
  }

  function trigger_update_SL(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    OrderBookStructsV1.UpdatePositionFieldOrder memory o = orderBook
      .readAndDeleteUpdatePositionOrder(_positionId);

    require(
      o.orderType == OrderBookStructsV1.UpdatePositionFieldOrderType.UPDATE_SL,
      "UPDATE_ORDER_NOT_SL"
    );

    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);

    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // ** Market order timestamp validity **
    validateMarketOrderTimestampInternal(o.timestamp, validatedPrice.timestamp);

    safelyIncreaseTriggersPerBlock();

    uint64 triggerPrice = validatedPrice.price;

    safePositionSingleFieldUpdateInternal(
      msg.sender,
      _positionId,
      o.orderType,
      TradingEnumsV1.PositionField.SL,
      o.fieldValueA,
      triggerPrice
    );
  }

  function trigger_update_TP_and_SL(
    bytes32 _positionId,
    bytes[] calldata pricePayload
  ) external payable notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    OrderBookStructsV1.UpdatePositionFieldOrder memory o = orderBook
      .readAndDeleteUpdatePositionOrder(_positionId);

    require(
      o.orderType ==
        OrderBookStructsV1.UpdatePositionFieldOrderType.UPDATE_TP_AND_SL,
      "UPDATE_ORDER_NOT_TP_AND_SL"
    );

    (, , uint16 pairId, , ) = tradingFloor.getPositionTriggerInfo(_positionId);

    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairWithSafeguardsInternal(
        pairId,
        msg.value,
        pricePayload
      );

    // ** Market order timestamp validity **
    validateMarketOrderTimestampInternal(o.timestamp, validatedPrice.timestamp);

    safelyIncreaseTriggersPerBlock();

    uint64 triggerPrice = validatedPrice.price;

    // Update TP
    require(
      safePositionSingleFieldUpdateInternal(
        msg.sender,
        _positionId,
        o.orderType,
        TradingEnumsV1.PositionField.TP,
        o.fieldValueA,
        triggerPrice
      ),
      "FAILED_TP_UPDATE"
    );

    // Update SL
    require(
      safePositionSingleFieldUpdateInternal(
        msg.sender,
        _positionId,
        o.orderType,
        TradingEnumsV1.PositionField.SL,
        o.fieldValueB,
        triggerPrice
      ),
      "FAILED_SL_UPDATE"
    );
  }

  function trigger_timeout_updatePosition(
    bytes32 _positionId
  ) external notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    OrderBookStructsV1.UpdatePositionFieldOrder memory o = orderBook
      .readAndDeleteUpdatePositionOrder(_positionId);

    require(
      block.timestamp >= o.timestamp + marketOrdersTimeout,
      "WAIT_TIMEOUT"
    );

    emit PositionUpdateTimeoutTriggered(
      msg.sender,
      _positionId,
      o.orderType,
      o.fieldValueA,
      o.fieldValueB
    );
  }

  function safePositionSingleFieldUpdateInternal(
    address triggerer,
    bytes32 _positionId,
    OrderBookStructsV1.UpdatePositionFieldOrderType orderType,
    TradingEnumsV1.PositionField positionField,
    uint64 fieldValue,
    uint64 triggerPrice
  ) internal returns (bool) {
    try
      tradingFloor.updateOpenedPosition(
        _positionId,
        positionField,
        fieldValue,
        triggerPrice
      )
    {
      emit UpdatePositionSingleFieldExecuted(
        triggerer,
        _positionId,
        orderType,
        positionField,
        fieldValue,
        triggerPrice
      );

      return true;
    } catch Error(string memory error) {
      // Note : Will happen from Normal 'require'
      emit UpdatePositionSingleFieldRejected(
        triggerer,
        _positionId,
        orderType,
        positionField,
        fieldValue,
        triggerPrice,
        error,
        0
      );

      return false;
    } catch (bytes memory err) {
      //  CapError (should only happen when updating TP)
      if (bytes4(err) == LexErrors.CapError.selector) {
        require(
          positionField == TradingEnumsV1.PositionField.TP,
          "CAP_ERROR_NOT_ON_TP"
        );

        LexErrors.CapType capType;
        uint256 value;
        assembly {
          capType := mload(add(err, 0x24))
          value := mload(add(err, 0x44))
        }

        emit UpdatePositionSingleFieldRejected(
          triggerer,
          _positionId,
          orderType,
          positionField,
          fieldValue,
          triggerPrice,
          "CAP_ERROR",
          uint(capType)
        );
        return false;
      } else {
        revert("UNKNOWN_CUSTOM_ERROR");
      }
    }
  }

  // ***** Market Requests Timeout Triggers *****

  function trigger_timeout_marketOpen(
    bytes32 _positionId
  ) external notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (
      TradingEnumsV1.PositionPhase phase,
      uint timestamp,
      uint16 pairId,
      ,

    ) = tradingFloor.getPositionTriggerInfo(_positionId);

    require(timestamp > 0, "NO_SUCH_POSITION");
    require(
      phase == TradingEnumsV1.PositionPhase.OPEN_MARKET,
      "NOT_OPEN_MARKET"
    );
    require(block.timestamp >= timestamp + marketOrdersTimeout, "WAIT_TIMEOUT");

    tradingFloor.cancelPendingPosition(
      _positionId,
      TradingEnumsV1.OpenOrderType.MARKET,
      marketOrderCancelFeeFraction
    );

    emit MarketOpenTimeoutTriggered(msg.sender, _positionId, pairId);
  }

  function trigger_timeout_marketClose(
    bytes32 _positionId
  ) external notDoneOrPaused onlyAllowedTriggerAccount nonReentrant {
    (
      TradingEnumsV1.PositionPhase phase,
      uint timestamp,
      uint16 pairId,
      ,

    ) = tradingFloor.getPositionTriggerInfo(_positionId);

    require(timestamp > 0, "NO_SUCH_POSITION");
    require(
      phase == TradingEnumsV1.PositionPhase.CLOSE_MARKET,
      "NOT_CLOSE_MARKET"
    );
    require(block.timestamp >= timestamp + marketOrdersTimeout, "WAIT_TIMEOUT");

    tradingFloor.cancelMarketCloseForPosition(
      _positionId,
      TradingEnumsV1.CloseOrderType.MARKET,
      marketOrderCancelFeeFraction
    );

    emit MarketCloseTimeoutTriggered(msg.sender, _positionId, pairId);
  }

  // ***** Price Validations Utils *****

  /**
   * Validates the payload and reverts if the price confidence is too high
   */
  function validatePriceForPairWithSafeguardsInternal(
    uint pairId,
    uint nativePayment,
    bytes[] calldata pricePayload
  ) internal returns (IPriceValidatorV1.ValidatedPrice memory) {
    IPriceValidatorV1.ValidatedPrice
      memory validatedPrice = validatePriceForPairInternal(
        pairId,
        nativePayment,
        pricePayload
      );

    uint maxConfidenceF = maxConfidenceFractionForPair[pairId];

    uint maxAllowedConfidence = calculateFractionInternal(
      uint(validatedPrice.price),
      maxConfidenceF
    );
    require(
      validatedPrice.confidence <= maxAllowedConfidence,
      "CONFIDENCE_RANGE_TOO_WIDE"
    );
    require(
      validatedPrice.timestamp <= block.timestamp,
      "FUTURE_PRICE_REPORTED"
    );

    return validatedPrice;
  }

  function validatePriceForPairInternal(
    uint pairIndex,
    uint nativePayment,
    bytes[] calldata pricePayload
  ) internal returns (IPriceValidatorV1.ValidatedPrice memory) {
    return
      priceValidator.validatePrice{value: nativePayment}(
        pairIndex,
        pricePayload
      );
  }

  /**
   * The time frame for triggering market orders is [orderTimestamp + minTriggerPeriodForMarketOrders, orderTimestamp + maxTriggerPeriodForMarketOrders]
   * Both the block.timestamp and the price timestamp MUST be withing this frame
   */
  function validateMarketOrderTimestampInternal(
    uint pendingMarketOrderTimestamp,
    uint priceTimestamp
  ) internal view {
    uint orderActivationEarliestTimestamp = pendingMarketOrderTimestamp +
      minTriggerPeriodForMarketOrders;
    uint orderActivationLatestTimestamp = pendingMarketOrderTimestamp +
      maxTriggerPeriodForMarketOrders;

    require(
      block.timestamp >= orderActivationEarliestTimestamp,
      "MARKET_ORDER_TRIGGER_TOO_SOON"
    );
    require(
      block.timestamp <= orderActivationLatestTimestamp,
      "MARKET_ORDER_TRIGGER_TOO_LATE"
    );
    require(
      priceTimestamp >= orderActivationEarliestTimestamp &&
        priceTimestamp <= orderActivationLatestTimestamp,
      "MARKET_ORDER_PRICE_OUT_OF_TIME_FRAME"
    );
  }

  function validateLimitOrderTimestampInternal(
    uint pendingLimitOrderTimestamp,
    uint priceTimestamp
  ) internal view {
    // ** Limit order timestamp validity **
    uint orderActivationEarliestTimestamp = pendingLimitOrderTimestamp +
      minTriggerPeriodForLimitOrders;

    require(
      block.timestamp >= orderActivationEarliestTimestamp,
      "LIMIT_ORDER_TRIGGER_TOO_SOON"
    );
    // The price must be reported after the limit order activation timestamp
    require(
      priceTimestamp >= orderActivationEarliestTimestamp,
      "LIMIT_ORDER_PRICE_OUT_OF_TIME_FRAME"
    );

    // The reported price cannot be too long in the past
    validateTriggerPriceRecentInternal(
      priceTimestamp,
      triggerPriceFreshnessTimeRange
    );
  }

  /**
   * @notice ensures the given timestamp is not older than the given window (in seconds)
   */
  function validateTriggerPriceRecentInternal(
    uint priceTimestamp,
    uint acceptedWindow
  ) internal view {
    uint oldestTimestamp = block.timestamp - acceptedWindow;
    require(priceTimestamp >= oldestTimestamp, "PRICE_TOO_OLD");
    // Sanity, price cannot be from the future
    require(priceTimestamp <= block.timestamp, "PRICE_TOO_NEW");
  }

  // ***** Limitation functions *****

  function safelyIncreaseTriggersPerBlock() internal {
    uint currentBlockTriggers = triggersPerBlock[block.number];
    require(
      currentBlockTriggers < maxTriggersPerBlock,
      "MAX_TRIGGERS_PER_BLOCK"
    );
    triggersPerBlock[block.number] = currentBlockTriggers + 1;
  }

  // ***** Internal Utils *****

  function calculateFractionInternal(
    uint amount,
    uint fraction
  ) internal pure returns (uint) {
    return (amount * fraction) / FRACTION_SCALE;
  }
}

File 2 of 25 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 3 of 25 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 25 : AcceptableImplementationClaimableAdminStorage.sol
// 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;
}

File 5 of 25 : ClaimableAdmin.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./AcceptableImplementationClaimableAdminStorage.sol";

/**
 * @title Claimable Admin
 */
contract ClaimableAdmin is ClaimableAdminStorage {
  /**
   * @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 ***/

  /**
   * @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);
  }
}

File 6 of 25 : IContractRegistryBase.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface IContractRegistryBase {
  function isImplementationValidForProxy(
    bytes32 proxyNameHash,
    address _implementation
  ) external view returns (bool);
}

File 7 of 25 : CommonScales.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/**
 * @dev only use immutables and constants in this contract
 */
contract CommonScales {
  uint256 public constant PRECISION = 1e18; // 18 decimals

  uint256 public constant LEVERAGE_SCALE = 100; // 2 decimal points

  uint256 public constant FRACTION_SCALE = 100000; // 5 decimal points

  uint256 public constant ACCURACY_IMPROVEMENT_SCALE = 1e9;

  function calculateLeveragedPosition(
    uint256 collateral,
    uint256 leverage
  ) internal pure returns (uint256) {
    return (collateral * leverage) / LEVERAGE_SCALE;
  }
}

File 8 of 25 : IFundingRateModel.sol
// 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);
}

File 9 of 25 : IGlobalLock.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface IGlobalLock {
  function lock() external;
  function freeLock() external;
}

File 10 of 25 : IInterestRateModel.sol
// 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);
}

File 11 of 25 : ILexPoolV1.sol
// 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);
}

File 12 of 25 : IOrderBookV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

// import "./ITokenV1.sol";
import "./OrderBookStructsV1.sol";
import "./TradingFloorStructsV1.sol";

interface IOrderBookFunctionalityV1 is OrderBookStructsV1 {
  // Update Position Orders

  function storeUpdatePositionSingleFieldOrder(
    bytes32 _positionId,
    UpdatePositionFieldOrderType orderType,
    uint64 fieldValue
  ) external returns (UpdatePositionFieldOrder memory);

  function storeUpdatePositionDoubleFieldOrder(
    bytes32 _positionId,
    UpdatePositionFieldOrderType orderType,
    uint64 fieldValueA,
    uint64 fieldValueB
  ) external returns (UpdatePositionFieldOrder memory);

  function readAndDeleteUpdatePositionOrder(
    bytes32 _positionId
  ) external returns (UpdatePositionFieldOrder memory order);
}

interface IOrderBookV1 is IOrderBookFunctionalityV1 {
  function PRECISION() external pure returns (uint);

  // *** Public Storage addresses ***

  function tradingFloor() external view returns (address);

  // *** Public Storage params ***

  function pendingUpdateTradeFieldOrdersById(
    bytes32 positionId
  ) external view returns (UpdatePositionFieldOrder memory);
}

File 13 of 25 : IPoolAccountantV1.sol
// 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);
}

File 14 of 25 : IPriceValidatorV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface IPriceValidatorV1 {
  // uint constant PRICE_SCALE = 1e8;

  struct ValidatedPrice {
    uint256 timestamp;
    uint64 price; // Scaled to PRICE_SCALE
    uint64 confidence; // Scaled to PRICE_SCALE
  }

  function isPriceValidator() external view returns (bool);

  function getUpdateFee(
    bytes[] calldata updateData
  ) external view returns (uint256 feeAmount);

  function validatePrice(
    uint256 pairIndex,
    bytes[] calldata updateData
  ) external payable returns (ValidatedPrice memory validatedPrice);
}

File 15 of 25 : IRegistryV1.sol
// 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);
}

File 16 of 25 : ITradingFloorV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./TradingFloorStructsV1.sol";
import "./IPoolAccountantV1.sol";
import "./ILexPoolV1.sol";

interface ITradingFloorV1Functionality is TradingFloorStructsV1 {
  function supportNewSettlementAsset(
    address _asset,
    address _lexPool,
    address _poolAccountant
  ) external;

  function getPositionTriggerInfo(
    bytes32 _positionId
  )
    external
    view
    returns (
      PositionPhase positionPhase,
      uint64 timestamp,
      uint16 pairId,
      bool long,
      uint32 spreadReductionF
    );

  function getPositionPortalInfo(
    bytes32 _positionId
  )
    external
    view
    returns (
      PositionPhase positionPhase,
      uint64 inPhaseSince,
      address positionTrader
    );

  function storePendingPosition(
    OpenOrderType _orderType,
    PositionRequestIdentifiers memory _requestIdentifiers,
    PositionRequestParams memory _requestParams,
    uint32 _spreadReductionF
  ) external returns (bytes32 positionId);

  function setOpenedPositionToMarketClose(
    bytes32 _positionId,
    uint64 _minPrice,
    uint64 _maxPrice
  ) external;

  function cancelPendingPosition(
    bytes32 _positionId,
    OpenOrderType _orderType,
    uint feeFraction
  ) external;

  function cancelMarketCloseForPosition(
    bytes32 _positionId,
    CloseOrderType _orderType,
    uint feeFraction
  ) external;

  function updatePendingPosition_openLimit(
    bytes32 _positionId,
    uint64 _minPrice,
    uint64 _maxPrice,
    uint64 _tp,
    uint64 _sl
  ) external;

  function openNewPosition_market(
    bytes32 _positionId,
    uint64 assetEffectivePrice,
    uint256 feeForCancellation
  ) external;

  function openNewPosition_limit(
    bytes32 _positionId,
    uint64 assetEffectivePrice,
    uint256 feeForCancellation
  ) external;

  function closeExistingPosition_Market(
    bytes32 _positionId,
    uint64 assetPrice,
    uint64 effectivePrice
  ) external;

  function closeExistingPosition_Limit(
    bytes32 _positionId,
    LimitTrigger limitTrigger,
    uint64 assetPrice,
    uint64 effectivePrice
  ) external;

  // Manage open trade
  function updateOpenedPosition(
    bytes32 _positionId,
    PositionField updateField,
    uint64 fieldValue,
    uint64 effectivePrice
  ) external;

  // Fees
  function collectFee(address _asset, FeeType _feeType, address _to) external;
}

interface ITradingFloorV1 is ITradingFloorV1Functionality {
  function PRECISION() external pure returns (uint);

  // *** Views ***

  function pairTradersArray(
    address _asset,
    uint _pairIndex
  ) external view returns (address[] memory);

  function generatePositionHashId(
    address settlementAsset,
    address trader,
    uint16 pairId,
    uint32 index
  ) external pure returns (bytes32 hashId);

  // *** Public Storage addresses ***

  function lexPoolForAsset(address asset) external view returns (ILexPoolV1);

  function poolAccountantForAsset(
    address asset
  ) external view returns (IPoolAccountantV1);

  function registry() external view returns (address);

  // *** Public Storage params ***

  function positionsById(bytes32 id) external view returns (Position memory);

  function positionIdentifiersById(
    bytes32 id
  ) external view returns (PositionIdentifiers memory);

  function positionLimitsInfoById(
    bytes32 id
  ) external view returns (PositionLimitsInfo memory);

  function triggerPricesById(
    bytes32 id
  ) external view returns (PositionTriggerPrices memory);

  function pairTradersInfo(
    address settlementAsset,
    address trader,
    uint pairId
  ) external view returns (PairTraderInfo memory);

  function spreadReductionsP(uint) external view returns (uint);

  function maxSlF() external view returns (uint);

  function maxTradesPerPair() external view returns (uint);

  function maxSanityProfitF() external view returns (uint);

  function feesMap(
    address settlementAsset,
    FeeType feeType
  ) external view returns (uint256);
}

File 17 of 25 : LexErrors.sol
// 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);
}

File 18 of 25 : LexPoolAdminEnums.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

interface LexPoolAdminEnums {
  enum LexPoolAddressesEnum {
    none,
    poolAccountant,
    pnlRole
  }

  enum LexPoolNumbersEnum {
    none,
    maxExtraWithdrawalAmountF,
    epochsDelayDeposit,
    epochsDelayRedeem,
    epochDuration,
    minDepositAmount
  }
}

File 19 of 25 : OrderBookStructsV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

// import "./ITokenV1.sol";
import "./TradingFloorStructsV1.sol";

interface OrderBookStructsV1 {
  enum UpdatePositionFieldOrderType {
    NONE,
    UPDATE_TP,
    UPDATE_SL,
    UPDATE_TP_AND_SL
  }

  struct UpdatePositionFieldOrder {
    // Slot 0
    bytes32 positionId; // 32 bytes
    // Slot 1
    UpdatePositionFieldOrderType orderType; // 01 bytes
    uint64 timestamp; // 08 bytes
    uint64 fieldValueA; // 08 bytes
    uint64 fieldValueB; // 08 bytes
  }
}

File 20 of 25 : TradingEnumsV1.sol
// 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
  }
}

File 21 of 25 : TradingFloorStructsV1.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./TradingEnumsV1.sol";

interface TradingFloorStructsV1 is TradingEnumsV1 {
  enum AdminNumericParam {
    NONE,
    MAX_TRADES_PER_PAIR,
    MAX_SL_F,
    MAX_SANITY_PROFIT_F
  }

  /**
   * @dev Memory struct for identifiers
   */
  struct PositionRequestIdentifiers {
    address trader;
    uint16 pairId;
    address settlementAsset;
    uint32 positionIndex;
  }

  struct PositionRequestParams {
    bool long;
    uint256 collateral; // Settlement Asset Decimals
    uint32 leverage;
    uint64 minPrice; // PRICE_SCALE
    uint64 maxPrice; // PRICE_SCALE
    uint64 tp; // PRICE_SCALE
    uint64 sl; // PRICE_SCALE
    uint64 tpByFraction; // FRACTION_SCALE
    uint64 slByFraction; // FRACTION_SCALE
  }

  /**
   * @dev Storage struct for identifiers
   */
  struct PositionIdentifiers {
    // Slot 0
    address settlementAsset; // 20 bytes
    uint16 pairId; // 02 bytes
    uint32 index; // 04 bytes
    // Slot 1
    address trader; // 20 bytes
  }

  struct Position {
    // Slot 0
    uint collateral; // 32 bytes -- Settlement Asset Decimals
    // Slot 1
    PositionPhase phase; // 01 bytes
    uint64 inPhaseSince; // 08 bytes
    uint32 leverage; // 04 bytes
    bool long; // 01 bytes
    uint64 openPrice; // 08 bytes -- PRICE_SCALE (8)
    uint32 spreadReductionF; // 04 bytes -- FRACTION_SCALE (5)
  }

  /**
   * Holds the non liquidation limits for the position
   */
  struct PositionLimitsInfo {
    uint64 tpLastUpdated; // 08 bytes -- timestamp
    uint64 slLastUpdated; // 08 bytes -- timestamp
    uint64 tp; // 08 bytes -- PRICE_SCALE (8)
    uint64 sl; // 08 bytes -- PRICE_SCALE (8)
  }

  /**
   * Holds the prices for opening (and market closing) of a position
   */
  struct PositionTriggerPrices {
    uint64 minPrice; // 08 bytes -- PRICE_SCALE
    uint64 maxPrice; // 08 bytes -- PRICE_SCALE
    uint64 tpByFraction; // 04 bytes -- FRACTION_SCALE
    uint64 slByFraction; // 04 bytes -- FRACTION_SCALE
  }

  /**
   * @dev administration struct, used to keep tracks on the 'PairTraders' list and
   *      to limit the amount of positions a trader can have
   */
  struct PairTraderInfo {
    uint32 positionsCounter; // 04 bytes
    uint32 positionInArray; // 04 bytes (the index + 1)
    // Note : Can add more fields here
  }
}

File 22 of 25 : SystemLocker.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../interfaces/IGlobalLock.sol";

/**
 * @notice Common contract to handle the global system locks
 * @dev This contract MUST NOT have any storage variables to not affect the storage layout
 */
contract SystemLocker {
  address private immutable globalLock;

  constructor(address _globalLock) {
    globalLock = _globalLock;
  }

  // ***** Reentrancy Guard *****

  /**
   * @dev Prevents a contract from calling itself, directly or indirectly.
   */
  modifier nonReentrant() {
    _beforeNonReentrant();
    _;
    _afterNonReentrant();
  }

  /**
   * @dev Tries to get the system lock
   */
  function _beforeNonReentrant() private {
    IGlobalLock(globalLock).lock();
  }

  /**
   * @dev Releases the system lock
   */
  function _afterNonReentrant() private {
    IGlobalLock(globalLock).freeLock();
  }
}

File 23 of 25 : ConfidenceChecker.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

/**
 * @title ConfidenceChecker
 * @dev Base utility contract for storing confidence levels fractions for prices
 */
contract ConfidenceChecker {
  // ***** Immutables *****

  uint public immutable MAX_ALLOWED_CONFIDENCE_FRACTION;

  // ***** Storage *****

  mapping(uint => uint32) public maxConfidenceFractionForPair; // FRACTION_SCALE (5)

  // ***** Events *****

  event MaxConfidenceForPairSet(
    uint indexed pairId,
    uint maxConfidenceFraction
  );

  // ***** Constructor *****

  constructor(uint _maxAllowedConfidenceFraction) {
    MAX_ALLOWED_CONFIDENCE_FRACTION = _maxAllowedConfidenceFraction;
  }

  // ***** Internal Functions *****

  function setMaxConfidenceForPairInternal(
    uint _pairId,
    uint32 _maxConfidenceFractionForPair
  ) internal {
    require(
      _maxConfidenceFractionForPair <= MAX_ALLOWED_CONFIDENCE_FRACTION,
      "CONFIDENCE_FRACTION_TOO_HIGH"
    );
    maxConfidenceFractionForPair[_pairId] = _maxConfidenceFractionForPair;
    emit MaxConfidenceForPairSet(_pairId, _maxConfidenceFractionForPair);
  }
}

File 24 of 25 : PriceAdjustmentBase.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../Common/CommonScales.sol";

/**
 * @title PriceAdjustmentBase
 * @dev Allows for adjustment of prices by using a simple spread mechanism
 */
contract PriceAdjustmentBase is CommonScales {
  // ***** Immutables *****

  uint public immutable MAX_ALLOWED_SPREAD_FRACTION; // FRACTION_SCALE (5)

  // ***** Storage *****

  mapping(uint => uint32) public spreadFractionForPair; // FRACTION_SCALE (5)

  // ***** Events *****

  event SpreadFractionForPairSet(uint indexed pairId, uint slippage);

  // ***** Constructor *****

  constructor(uint _maxAllowedSpreadReduction) {
    MAX_ALLOWED_SPREAD_FRACTION = _maxAllowedSpreadReduction;
  }

  // ***** Internal Functions *****

  function setSpreadFractionForPairInternal(
    uint _pairId,
    uint32 _spreadF
  ) internal {
    require(_spreadF <= MAX_ALLOWED_SPREAD_FRACTION, "SPREAD_TOO_HIGH");
    spreadFractionForPair[_pairId] = _spreadF;
    emit SpreadFractionForPairSet(_pairId, _spreadF);
  }

  function calculatePostSpreadPrice(
    uint pairId,
    uint64 basePrice,
    uint32 spreadReductionF,
    bool increase
  ) internal view returns (uint64) {
    require(spreadReductionF <= FRACTION_SCALE, "SPREAD_REDUCTION_TOO_HIGH");
    uint64 spreadPart = uint64(
      (spreadFractionForPair[pairId] * uint256(basePrice)) / FRACTION_SCALE
    );
    uint64 safeSpreadPart = spreadPart -
      uint64(((spreadPart * spreadReductionF) / FRACTION_SCALE));
    return increase ? basePrice + safeSpreadPart : basePrice - safeSpreadPart;
  }
}

File 25 of 25 : TriggersPermissionBase.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

/**
 * @title TriggersPermissionBase
 * @dev Allows for a basic whitelisting mechanism
 */
contract TriggersPermissionBase {
  using EnumerableSet for EnumerableSet.AddressSet;

  // ***** Storage *****

  EnumerableSet.AddressSet private triggerPermissionSet;

  // ***** Modifiers *****

  modifier onlyAllowedTriggerAccount() {
    require(isAllowedToTrigger(msg.sender), "NOT_ALLOWED_TO_TRIGGER");
    _;
  }

  // ***** Events *****

  event TriggerAccountAllowed(address indexed account);
  event TriggerAccountDisallowed(address indexed account);

  // ***** View *****

  function isAllowedToTrigger(address account) public view returns (bool) {
    return triggerPermissionSet.contains(account);
  }

  function getAllTriggerPermissionedAccounts()
    public
    view
    returns (address[] memory)
  {
    return triggerPermissionSet.values();
  }

  // ***** Internal Functions *****

  function allowTriggerAccountInternal(address account) internal {
    require(!isAllowedToTrigger(account), "ACCOUNT_ALREADY_ALLOWED");
    triggerPermissionSet.add(account);
    emit TriggerAccountAllowed(account);
  }

  function disallowTriggerAccountInternal(address account) internal {
    require(isAllowedToTrigger(account), "ACCOUNT_NOT_ALLOWED");
    triggerPermissionSet.remove(account);
    emit TriggerAccountDisallowed(account);
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ITradingFloorV1","name":"_tradingFloor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"value","type":"address"}],"name":"AddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum TradingEnumsV1.PositionPhase","name":"phase","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceTimestamp","type":"uint256"}],"name":"ClosePositionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"done","type":"bool"}],"name":"DoneToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceTimestamp","type":"uint256"}],"name":"LiquidationExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"}],"name":"MarketCloseTimeoutTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"}],"name":"MarketOpenTimeoutTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pairId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxConfidenceFraction","type":"uint256"}],"name":"MaxConfidenceForPairSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","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":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum TradingEnumsV1.PositionPhase","name":"phase","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceTimestamp","type":"uint256"}],"name":"OpenPositionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PausedToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum OrderBookStructsV1.UpdatePositionFieldOrderType","name":"orderType","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"fieldValueA","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"fieldValueB","type":"uint64"}],"name":"PositionUpdateTimeoutTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceTimestamp","type":"uint256"}],"name":"SlExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pairId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"SpreadFractionForPairSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceTimestamp","type":"uint256"}],"name":"TpExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"TriggerAccountAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"TriggerAccountDisallowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum OrderBookStructsV1.UpdatePositionFieldOrderType","name":"orderType","type":"uint8"},{"indexed":false,"internalType":"enum TradingEnumsV1.PositionField","name":"positionField","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fieldValue","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"triggerPrice","type":"uint64"}],"name":"UpdatePositionSingleFieldExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"triggerer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"positionId","type":"bytes32"},{"indexed":true,"internalType":"enum OrderBookStructsV1.UpdatePositionFieldOrderType","name":"orderType","type":"uint8"},{"indexed":false,"internalType":"enum TradingEnumsV1.PositionField","name":"positionField","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fieldValue","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"triggerPrice","type":"uint64"},{"indexed":false,"internalType":"string","name":"rejectionReason","type":"string"},{"indexed":false,"internalType":"uint256","name":"rejectionValue","type":"uint256"}],"name":"UpdatePositionSingleFieldRejected","type":"event"},{"inputs":[],"name":"ACCURACY_IMPROVEMENT_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRACTION_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVERAGE_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ALLOWED_CONFIDENCE_FRACTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ALLOWED_SPREAD_FRACTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"allowTriggerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"disallowTriggerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllTriggerPermissionedAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairId","type":"uint256"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"getValidatedPrice","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint64","name":"price","type":"uint64"},{"internalType":"uint64","name":"confidence","type":"uint64"}],"internalType":"struct IPriceValidatorV1.ValidatedPrice","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAllowedToTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketOrderCancelFeeFraction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketOrderTightTimeRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketOrdersTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxConfidenceFractionForPair","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTriggerPeriodForMarketOrders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTriggersPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTriggerPeriodForLimitOrders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTriggerPeriodForMarketOrders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openPositionCancellationFeeFraction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"orderBook","outputs":[{"internalType":"contract IOrderBookV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceValidator","outputs":[{"internalType":"contract IPriceValidatorV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketOrderCancelFeeFraction","type":"uint256"}],"name":"setMarketOrderCancelFeeFraction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketOrderTightTimeRange","type":"uint256"}],"name":"setMarketOrderTightTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketOrdersTimeout","type":"uint256"}],"name":"setMarketOrdersTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairId","type":"uint256"},{"internalType":"uint32","name":"maxConfidenceFraction","type":"uint32"}],"name":"setMaxConfidenceForPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTriggerPeriodForMarketOrders","type":"uint256"}],"name":"setMaxTriggerPeriodForMarketOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTriggersPerBlock","type":"uint256"}],"name":"setMaxTriggersPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTriggerPeriodForLimitOrders","type":"uint256"}],"name":"setMinTriggerPeriodForLimitOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTriggerPeriodForMarketOrders","type":"uint256"}],"name":"setMinTriggerPeriodForMarketOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_openPositionCancellationFeeFraction","type":"uint256"}],"name":"setOpenPositionCancellationFeeFraction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceValidator","type":"address"}],"name":"setPriceValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairId","type":"uint256"},{"internalType":"uint32","name":"spreadFraction","type":"uint32"}],"name":"setSpreadFractionForPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_triggerPriceFreshnessTimeRange","type":"uint256"}],"name":"setTriggerPriceFreshnessTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spreadFractionForPair","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleDone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"togglePause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tradingFloor","outputs":[{"internalType":"contract ITradingFloorV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggerPriceFreshnessTimeRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_closeTrade_LIQ","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_closeTrade_SL","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_closeTrade_TP","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_closeTrade_market","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_openTrade_limit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_openTrade_market","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"trigger_timeout_marketClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"trigger_timeout_marketOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"trigger_timeout_updatePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_update_SL","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_update_TP","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"},{"internalType":"bytes[]","name":"pricePayload","type":"bytes[]"}],"name":"trigger_update_TP_and_SL","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"triggersPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101206040526003600755603c600855603c600955603c600a5560b4600b55610708600c556103e8620186a0600162000039919062000291565b620000459190620002bd565b600d556103e86200005b620186a0600262000291565b620000679190620002bd565b600e556003600f553480156200007c57600080fd5b5060405162004ee838038062004ee88339810160408190526200009f91620002f9565b806001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001049190620002f9565b606462000116620186a0600162000291565b620001229190620002bd565b606462000134620186a0600a62000291565b620001409190620002bd565b600080546001600160a01b0319163317905560805260a0526001600160a01b0390811660c0528116620001a85760405162461bcd60e51b815260206004820152600c60248201526b57524f4e475f504152414d5360a01b604482015260640160405180910390fd5b6001600160a01b03811660e081905260408051637b10399960e01b81529051637b103999916004808201926020929091908290030181865afa158015620001f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002199190620002f9565b6001600160a01b031663776af5ba6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000257573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027d9190620002f9565b6001600160a01b0316610100525062000320565b8082028115828204841417620002b757634e487b7160e01b600052601160045260246000fd5b92915050565b600082620002db57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0381168114620002f657600080fd5b50565b6000602082840312156200030c57600080fd5b81516200031981620002e0565b9392505050565b60805160a05160c05160e05161010051614ab8620004306000396000818161076001528181610fc201528181611bb7015281816127100152612dd801526000818161039801528181610b3401528181610cd301528181611198015281816112f00152818161141b015281816115c901528181611817015281816118b1015281816119e101528181611ca201528181611e1001528181611eaa01528181611fd701528181612158015281816123080152818161242d01528181612508015281816127fb01528181612b4701528181612c9e01528181612ecd015261397d015260008181613339015261366101526000818161051501526136bc01526000818161098d0152613c460152614ab86000f3fe6080604052600436106103815760003560e01c8063776af5ba116101d1578063ad1f2b5611610102578063c4ae3168116100a0578063e9c714f21161006f578063e9c714f214610a37578063f851a44014610a4c578063fae5a83f14610a6c578063fd057e9414610a8c57600080fd5b8063c4ae3168146109cf578063d99dc0c1146109e4578063e231377014610a04578063e8051b0114610a2457600080fd5b8063b71f3cfe116100dc578063b71f3cfe14610943578063b81bfa051461095b578063b88750a91461097b578063bfc084d9146109af57600080fd5b8063ad1f2b56146108f4578063b187bd2614610909578063b71d1a0c1461092357600080fd5b80639abf17821161016f578063a5b6020811610149578063a5b602081461088f578063a5e02c8d146108a5578063a9f7c521146108c5578063aaf5eb68146108d857600080fd5b80639abf17821461081c5780639f918f451461083c578063a1d627a11461086f57600080fd5b806380193b26116101ab57806380193b26146107ae57806381405205146107c557806386c7f19a146107db5780638f062227146107fd57600080fd5b8063776af5ba1461074e5780637f31c2db146107825780637f588b911461079857600080fd5b8063392503e0116102b65780634cdb06a5116102545780636c1bb5ca116102235780636c1bb5ca146106e8578063718ddc14146107085780637670d9481461071b578063771ad70d1461073b57600080fd5b80634cdb06a51461065a5780634d3691511461067a5780635d2cdfea1461068d5780636447dc8b146106d557600080fd5b8063410c0b7c11610290578063410c0b7c146105fb57806345b6171314610611578063490580e3146106275780634bdf19731461064757600080fd5b8063392503e0146105bd5780633b321666146105d35780633be3d626146105e657600080fd5b806326b4120a1161032357806333a01d32116102fd57806333a01d321461050357806336930d0b1461053757806336b669f714610557578063382672571461059d57600080fd5b806326b4120a146104935780632f86d7c2146104b357806333511e5e146104d357600080fd5b8063221407af1161035f578063221407af1461042857806322ede93c1461043d57806325577e9f14610453578063267822471461047357600080fd5b80630d3b0b761461038657806310b4cc13146103d757806320cb5976146103fb575b600080fd5b34801561039257600080fd5b506103ba7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103e357600080fd5b506103ed600d5481565b6040519081526020016103ce565b34801561040757600080fd5b506103ed610416366004614157565b60106020526000908152604090205481565b61043b6104363660046141bb565b610aac565b005b34801561044957600080fd5b506103ed600e5481565b34801561045f57600080fd5b5061043b61046e366004614218565b610db3565b34801561047f57600080fd5b506001546103ba906001600160a01b031681565b34801561049f57600080fd5b5061043b6104ae366004614157565b610deb565b3480156104bf57600080fd5b5061043b6104ce366004614157565b610e82565b3480156104df57600080fd5b506104f36104ee366004614248565b610f1e565b60405190151581526020016103ce565b34801561050f57600080fd5b506103ed7f000000000000000000000000000000000000000000000000000000000000000081565b34801561054357600080fd5b5061043b610552366004614157565b610f31565b61056a6105653660046141bb565b6110e8565b60408051825181526020808401516001600160401b039081169183019190915292820151909216908201526060016103ce565b3480156105a957600080fd5b5061043b6105b8366004614157565b611119565b3480156105c957600080fd5b506103ed600c5481565b61043b6105e13660046141bb565b611399565b3480156105f257600080fd5b5061043b6116a7565b34801561060757600080fd5b506103ed600a5481565b34801561061d57600080fd5b506103ed60075481565b34801561063357600080fd5b5061043b610642366004614157565b611733565b61043b6106553660046141bb565b611786565b34801561066657600080fd5b5061043b610675366004614157565b611abd565b61043b6106883660046141bb565b611b26565b34801561069957600080fd5b506106c06106a8366004614157565b60056020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016103ce565b61043b6106e33660046141bb565b611d7f565b3480156106f457600080fd5b5061043b610703366004614218565b6120a2565b61043b6107163660046141bb565b6120d6565b34801561072757600080fd5b5061043b610736366004614157565b61233f565b61043b6107493660046141bb565b61239c565b34801561075a57600080fd5b506103ba7f000000000000000000000000000000000000000000000000000000000000000081565b34801561078e57600080fd5b506103ed60085481565b3480156107a457600080fd5b506103ed60095481565b3480156107ba57600080fd5b506103ed620186a081565b3480156107d157600080fd5b506103ed600f5481565b3480156107e757600080fd5b506107f06125de565b6040516103ce9190614271565b34801561080957600080fd5b506011546104f390610100900460ff1681565b34801561082857600080fd5b5061043b610837366004614157565b6125ef565b34801561084857600080fd5b506106c0610857366004614157565b60046020526000908152604090205463ffffffff1681565b34801561087b57600080fd5b506006546103ba906001600160a01b031681565b34801561089b57600080fd5b506103ed600b5481565b3480156108b157600080fd5b5061043b6108c0366004614248565b61264c565b61043b6108d33660046141bb565b61267f565b3480156108e457600080fd5b506103ed670de0b6b3a764000081565b34801561090057600080fd5b506103ed606481565b34801561091557600080fd5b506011546104f39060ff1681565b34801561092f57600080fd5b5061043b61093e366004614248565b6128cb565b34801561094f57600080fd5b506103ed633b9aca0081565b34801561096757600080fd5b5061043b610976366004614157565b612973565b34801561098757600080fd5b506103ed7f000000000000000000000000000000000000000000000000000000000000000081565b3480156109bb57600080fd5b5061043b6109ca366004614157565b6129c6565b3480156109db57600080fd5b5061043b612a23565b3480156109f057600080fd5b5061043b6109ff366004614248565b612a95565b348015610a1057600080fd5b5061043b610a1f366004614157565b612ac8565b61043b610a323660046141bb565b612d47565b348015610a4357600080fd5b5061043b61303e565b348015610a5857600080fd5b506000546103ba906001600160a01b031681565b348015610a7857600080fd5b5061043b610a87366004614248565b61315c565b348015610a9857600080fd5b5061043b610aa7366004614157565b61329b565b601154610100900460ff1615610add5760405162461bcd60e51b8152600401610ad4906142b2565b60405180910390fd5b60115460ff1615610b005760405162461bcd60e51b8152600401610ad4906142d0565b610b0933610f1e565b610b255760405162461bcd60e51b8152600401610ad4906142f0565b610b2d613337565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395be5050876040518263ffffffff1660e01b8152600401610b8091815260200190565b60a060405180830381865afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc1919061434c565b505092506001600160401b03169250925060008211610c1c5760405162461bcd60e51b81526020600482015260176024820152762727afa822a72224a723afa6a0a925a2aa2fa7a92222a960491b6044820152606401610ad4565b6004836005811115610c3057610c306143c4565b14610c705760405162461bcd60e51b815260206004820152601060248201526f1393d517d0d313d4d157d3505492d15560821b6044820152606401610ad4565b6000610c828261ffff163488886133ac565b9050610c928382600001516134bb565b602081015180610ca06135e7565b602083015160405163651d1d4160e11b8152600481018b90526001600160401b03918216602482015290821660448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ca3a3a8290606401600060405180830381600087803b158015610d1f57600080fd5b505af1158015610d33573d6000803e3d6000fd5b50505050856005811115610d4957610d496143c4565b6020848101518551604080516001600160401b038781168252909316938301939093528183015290518b9133917f5b5ec0827d50049e9f15c1d5c28dc87d620987ef82a18f0b98afac1c76076d3d9181900360600190a4505050505050610dae61365f565b505050565b6000546001600160a01b03163314610ddd5760405162461bcd60e51b8152600401610ad4906143da565b610de782826136ba565b5050565b6000546001600160a01b03163314610e155760405162461bcd60e51b8152600401610ad4906143da565b600b8190556040517f6d61726b65744f72646572546967687454696d6552616e67650000000000000081526019015b604051908190038120828252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab906020015b60405180910390a250565b6000546001600160a01b03163314610eac5760405162461bcd60e51b8152600401610ad4906143da565b6008548110610eeb5760405162461bcd60e51b815260206004820152600b60248201526a57524f4e475f56414c554560a81b6044820152606401610ad4565b60078190556040517f6d696e54726967676572506572696f64466f724d61726b65744f7264657273008152601f01610e44565b6000610f2b600283613781565b92915050565b601154610100900460ff1615610f595760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615610f7c5760405162461bcd60e51b8152600401610ad4906142d0565b610f8533610f1e565b610fa15760405162461bcd60e51b8152600401610ad4906142f0565b610fa9613337565b60405163c608b6c160e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190614438565b9050600a5481604001516001600160401b031661105491906144e8565b4210156110735760405162461bcd60e51b8152600401610ad4906144fb565b80602001516003811115611089576110896143c4565b60608201516080830151604080516001600160401b039384168152929091166020830152849133917f7b5b2e57aed6ee99244bd22f2b43e33e9fcbf0d77a9f425d59ee2d74e1c3795d910160405180910390a4506110e561365f565b50565b6040805160608101825260008082526020820181905291810191909152611111843485856133ac565b949350505050565b601154610100900460ff16156111415760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156111645760405162461bcd60e51b8152600401610ad4906142d0565b61116d33610f1e565b6111895760405162461bcd60e51b8152600401610ad4906142f0565b611191613337565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395be5050856040518263ffffffff1660e01b81526004016111e491815260200190565b60a060405180830381865afa158015611201573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611225919061434c565b505092506001600160401b031692509250600082116112565760405162461bcd60e51b8152600401610ad490614521565b600483600581111561126a5761126a6143c4565b146112aa5760405162461bcd60e51b815260206004820152601060248201526f1393d517d0d313d4d157d3505492d15560821b6044820152606401610ad4565b600a546112b790836144e8565b4210156112d65760405162461bcd60e51b8152600401610ad4906144fb565b600d54604051634ebe5c3360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691634ebe5c33916113299188916001919060040161454b565b600060405180830381600087803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b505060405161ffff8416925086915033907f89a3ecf5024675f1d0abc6dc42608fc41216f103c12c2c84f8ca3938bd055f0390600090a45050506110e561365f565b601154610100900460ff16156113c15760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156113e45760405162461bcd60e51b8152600401610ad4906142d0565b6113ed33610f1e565b6114095760405162461bcd60e51b8152600401610ad4906142f0565b611411613337565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395be5050896040518263ffffffff1660e01b815260040161146791815260200190565b60a060405180830381865afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a8919061434c565b9450945094506001600160401b031694509450600084116115045760405162461bcd60e51b81526020600482015260166024820152752727afa822a72224a723afa624a6a4aa2fa7a92222a960511b6044820152606401610ad4565b6002856005811115611518576115186143c4565b146115565760405162461bcd60e51b815260206004820152600e60248201526d1393d517d3d4115397d31253525560921b6044820152606401610ad4565b60006115688461ffff16348a8a6133ac565b90506115788582600001516137a6565b6020810151600061158f61ffff8716838688613870565b90506115996135e7565b600e54604051631ea9af6b60e01b8152600481018d90526001600160401b038316602482015260448101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631ea9af6b906064015b600060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b50505050876005811115611640576116406143c4565b6020848101518551604080516001600160401b038781168252909316938301939093528183015290518d9133917f60fab6e183a7c350210c0b457db01423b47aa3e72f5b735b8dbb3ecd3e8077439181900360600190a45050505050505050610dae61365f565b6000546001600160a01b031633146116d15760405162461bcd60e51b8152600401610ad4906143da565b6011805460ff610100808304821615810261ff001990931692909217928390556040517f8e47bd62470c6cba4d30c023548622607c9c84402a5655f2569b7934c36a9e4f936117299390049091161515815260200190565b60405180910390a1565b6000546001600160a01b0316331461175d5760405162461bcd60e51b8152600401610ad4906143da565b600f819055604051726d61785472696767657273506572426c6f636b60681b8152601301610e44565b601154610100900460ff16156117ae5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156117d15760405162461bcd60e51b8152600401610ad4906142d0565b6117da33610f1e565b6117f65760405162461bcd60e51b8152600401610ad4906142f0565b6117fe613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa158015611866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188a919061434c565b50506040516366307a4f60e01b815260048101889052909350600092506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691506366307a4f90602401608060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190614573565b905060008261ffff16116119435760405162461bcd60e51b8152600401610ad490614521565b600081606001516001600160401b0316116119885760405162461bcd60e51b81526020600482015260056024820152641393d7d4d360da1b6044820152606401610ad4565b60208101516001600160401b031660006119a861ffff85163488886133ac565b90506119b88282600001516137a6565b60208101516119c56135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916380a7f3d491611a1c918c916002919087906004016145fd565b600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b5050506020808401518451604080516001600160401b038088168252909316938301939093529181019190915261ffff87169150899033907fb03dbc9368faf0f8588dc8429c40a26ef9a637488f1ea5521a2ba2bfb5ff2016906060015b60405180910390a45050505050610dae61365f565b6000546001600160a01b03163314611ae75760405162461bcd60e51b8152600401610ad4906143da565b600e8190556040517f6f70656e506f736974696f6e43616e63656c6c6174696f6e466565467261637481526234b7b760e91b6020820152602301610e44565b601154610100900460ff1615611b4e5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615611b715760405162461bcd60e51b8152600401610ad4906142d0565b611b7a33610f1e565b611b965760405162461bcd60e51b8152600401610ad4906142f0565b611b9e613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015611c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2c9190614438565b9050600281602001516003811115611c4657611c466143c4565b14611c895760405162461bcd60e51b815260206004820152601360248201527215541110551157d3d491115497d393d517d4d3606a1b6044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa158015611cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d15919061434c565b5050925050506000611d2d8261ffff163487876133ac565b9050611d4a83604001516001600160401b031682600001516134bb565b611d526135e7565b600081602001519050611d72338886602001516002886060015186613963565b5050505050610dae61365f565b601154610100900460ff1615611da75760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615611dca5760405162461bcd60e51b8152600401610ad4906142d0565b611dd333610f1e565b611def5760405162461bcd60e51b8152600401610ad4906142f0565b611df7613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e83919061434c565b50506040516366307a4f60e01b815260048101889052909350600092506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691506366307a4f90602401608060405180830381865afa158015611ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f169190614573565b905060008261ffff1611611f3c5760405162461bcd60e51b8152600401610ad490614521565b600081604001516001600160401b031611611f815760405162461bcd60e51b815260206004820152600560248201526404e4f5f54560dc1b6044820152606401610ad4565b80516001600160401b03166000611f9e61ffff85163488886133ac565b9050611fae8282600001516137a6565b6020810151611fbb6135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916380a7f3d491612012918c916001919087906004016145fd565b600060405180830381600087803b15801561202c57600080fd5b505af1158015612040573d6000803e3d6000fd5b5050506020808401518451604080516001600160401b038088168252909316938301939093529181019190915261ffff87169150899033907fbe700227f721a08f3b755aa3348a63564c2c07890aba73de46372f7bffcaa2e290606001611aa8565b6000546001600160a01b031633146120cc5760405162461bcd60e51b8152600401610ad4906143da565b610de78282613c44565b601154610100900460ff16156120fe5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156121215760405162461bcd60e51b8152600401610ad4906142d0565b61212a33610f1e565b6121465760405162461bcd60e51b8152600401610ad4906142f0565b61214e613337565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395be5050896040518263ffffffff1660e01b81526004016121a491815260200190565b60a060405180830381865afa1580156121c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e5919061434c565b9450945094506001600160401b031694509450600084116122425760405162461bcd60e51b81526020600482015260176024820152762727afa822a72224a723afa6a0a925a2aa2fa7a92222a960491b6044820152606401610ad4565b6001856005811115612256576122566143c4565b146122955760405162461bcd60e51b815260206004820152600f60248201526e1393d517d3d4115397d3505492d155608a1b6044820152606401610ad4565b60006122a78461ffff16348a8a6133ac565b90506122b78582600001516134bb565b602081015160006122ce61ffff8716838688613870565b90506122d86135e7565b600e546040516303ad224560e61b8152600481018d90526001600160401b038316602482015260448101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063eb489140906064016115fc565b6000546001600160a01b031633146123695760405162461bcd60e51b8152600401610ad4906143da565b600c8190556040517f74726967676572507269636546726573686e65737354696d6552616e676500008152601e01610e44565b601154610100900460ff16156123c45760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156123e75760405162461bcd60e51b8152600401610ad4906142d0565b6123f033610f1e565b61240c5760405162461bcd60e51b8152600401610ad4906142f0565b612414613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa15801561247c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a0919061434c565b50509250505060008161ffff16116124ca5760405162461bcd60e51b8152600401610ad490614521565b60006124dc8261ffff163486866133ac565b60208101519091506124ec6135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916380a7f3d491612543918a916003919087906004016145fd565b600060405180830381600087803b15801561255d57600080fd5b505af1158015612571573d6000803e3d6000fd5b505050506020828101518351604080516001600160401b0386811682529093169383019390935281830152905161ffff851691889133917f086bdd0cdd4ae322dd6112d05bdf96c020e6b90cc84ee2d39941bd716e18fb92919081900360600190a4505050610dae61365f565b60606125ea6002613d11565b905090565b6000546001600160a01b031633146126195760405162461bcd60e51b8152600401610ad4906143da565b600d8190556040517f6d61726b65744f7264657243616e63656c4665654672616374696f6e000000008152601c01610e44565b6000546001600160a01b031633146126765760405162461bcd60e51b8152600401610ad4906143da565b6110e581613d1e565b601154610100900460ff16156126a75760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156126ca5760405162461bcd60e51b8152600401610ad4906142d0565b6126d333610f1e565b6126ef5760405162461bcd60e51b8152600401610ad4906142f0565b6126f7613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015612761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127859190614438565b905060018160200151600381111561279f5761279f6143c4565b146127e25760405162461bcd60e51b815260206004820152601360248201527205550444154455f4f524445525f4e4f545f545606c1b6044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa15801561284a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286e919061434c565b50509250505060006128868261ffff163487876133ac565b90506128a383604001516001600160401b031682600001516134bb565b6128ab6135e7565b600081602001519050611d72338886602001516001886060015186613963565b6000546001600160a01b031633146129115760405162461bcd60e51b81526020600482015260096024820152682737ba1020b236b4b760b91b6044820152606401610ad4565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a991015b60405180910390a15050565b6000546001600160a01b0316331461299d5760405162461bcd60e51b8152600401610ad4906143da565b600a819055604051721b585c9ad95d13dc99195c9cd51a5b595bdd5d606a1b8152601301610e44565b6000546001600160a01b031633146129f05760405162461bcd60e51b8152600401610ad4906143da565b60098190556040517f6d696e54726967676572506572696f64466f724c696d69744f726465727300008152601e01610e44565b6000546001600160a01b03163314612a4d5760405162461bcd60e51b8152600401610ad4906143da565b6011805460ff8082161560ff1990921682179092556040519116151581527fda88b5dfaac55549d4ddddd43a09d4b911233df354952ebc9ac2041aa185343690602001611729565b6000546001600160a01b03163314612abf5760405162461bcd60e51b8152600401610ad4906143da565b6110e581613dac565b601154610100900460ff1615612af05760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615612b135760405162461bcd60e51b8152600401610ad4906142d0565b612b1c33610f1e565b612b385760405162461bcd60e51b8152600401610ad4906142f0565b612b40613337565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395be5050856040518263ffffffff1660e01b8152600401612b9391815260200190565b60a060405180830381865afa158015612bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd4919061434c565b505092506001600160401b03169250925060008211612c055760405162461bcd60e51b8152600401610ad490614521565b6001836005811115612c1957612c196143c4565b14612c585760405162461bcd60e51b815260206004820152600f60248201526e1393d517d3d4115397d3505492d155608a1b6044820152606401610ad4565b600a54612c6590836144e8565b421015612c845760405162461bcd60e51b8152600401610ad4906144fb565b600d54604051636e01af8d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691636e01af8d91612cd791889160019190600401614649565b600060405180830381600087803b158015612cf157600080fd5b505af1158015612d05573d6000803e3d6000fd5b505060405161ffff8416925086915033907f5079795ec65f793d5a0ed74d8f8e1562b7795934b40612bf55cf0e5d55a3447990600090a45050506110e561365f565b601154610100900460ff1615612d6f5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615612d925760405162461bcd60e51b8152600401610ad4906142d0565b612d9b33610f1e565b612db75760405162461bcd60e51b8152600401610ad4906142f0565b612dbf613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015612e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4d9190614438565b9050600381602001516003811115612e6757612e676143c4565b14612eb45760405162461bcd60e51b815260206004820152601a60248201527f5550444154455f4f524445525f4e4f545f54505f414e445f534c0000000000006044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395be50509060240160a060405180830381865afa158015612f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f40919061434c565b5050925050506000612f588261ffff163487876133ac565b9050612f7583604001516001600160401b031682600001516134bb565b612f7d6135e7565b600081602001519050612f9d338886602001516001886060015186613963565b612fdc5760405162461bcd60e51b815260206004820152601060248201526f4641494c45445f54505f55504441544560801b6044820152606401610ad4565b612ff3338886602001516002886080015186613963565b6130325760405162461bcd60e51b815260206004820152601060248201526f4641494c45445f534c5f55504441544560801b6044820152606401610ad4565b50505050610dae61365f565b6001546001600160a01b03163314801561306257506001546001600160a01b031615155b6130ae5760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420746865204558495354494e472070656e64696e672061646d696e00006044820152606401610ad4565b60008054600180546001600160a01b038082166001600160a01b031980861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101612967565b6000546001600160a01b031633146131865760405162461bcd60e51b8152600401610ad4906143da565b806001600160a01b0316634535dc4c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e89190614659565b6132265760405162461bcd60e51b815260206004820152600f60248201526e10a83934b1b2ab30b634b230ba37b960891b6044820152606401610ad4565b600680546001600160a01b0319166001600160a01b0383161790556040516d283934b1b2ab30b634b230ba37b960911b8152600e016040519081900381206001600160a01b0383168252907f943e9d45a11aaae5d87503e3bc248665d9807856e5cf2bdb4a988bee4442278190602001610e77565b6000546001600160a01b031633146132c55760405162461bcd60e51b8152600401610ad4906143da565b60075481116133045760405162461bcd60e51b815260206004820152600b60248201526a57524f4e475f56414c554560a81b6044820152606401610ad4565b60088190556040517f6d617854726967676572506572696f64466f724d61726b65744f7264657273008152601f01610e44565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561339257600080fd5b505af11580156133a6573d6000803e3d6000fd5b50505050565b60408051606081018252600080825260208201819052918101829052906133d586868686613e45565b60008781526004602090815260408220549083015192935063ffffffff1691613407906001600160401b031683613ee0565b90508083604001516001600160401b031611156134665760405162461bcd60e51b815260206004820152601960248201527f434f4e464944454e43455f52414e47455f544f4f5f57494445000000000000006044820152606401610ad4565b82514210156134af5760405162461bcd60e51b815260206004820152601560248201527411955515549157d4149250d157d4915413d4951151605a1b6044820152606401610ad4565b50909695505050505050565b6000600754836134cb91906144e8565b90506000600854846134dd91906144e8565b90508142101561352f5760405162461bcd60e51b815260206004820152601d60248201527f4d41524b45545f4f524445525f545249474745525f544f4f5f534f4f4e0000006044820152606401610ad4565b8042111561357f5760405162461bcd60e51b815260206004820152601d60248201527f4d41524b45545f4f524445525f545249474745525f544f4f5f4c4154450000006044820152606401610ad4565b81831015801561358f5750808311155b6133a65760405162461bcd60e51b8152602060048201526024808201527f4d41524b45545f4f524445525f50524943455f4f55545f4f465f54494d455f4660448201526352414d4560e01b6064820152608401610ad4565b43600090815260106020526040902054600f5481106136415760405162461bcd60e51b81526020600482015260166024820152754d41585f54524947474552535f5045525f424c4f434b60501b6044820152606401610ad4565b61364c8160016144e8565b4360009081526010602052604090205550565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340da020f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561339257600080fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff1611156137225760405162461bcd60e51b815260206004820152600f60248201526e0a6a0a48a8288bea89e9ebe90928e9608b1b6044820152606401610ad4565b600082815260056020908152604091829020805463ffffffff191663ffffffff8516908117909155915191825283917ffe5fd0852fab5f8ba593533cf24a4b4b235704c0e06956d0a58cc2ca0a4b6b4491015b60405180910390a25050565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000600954836137b691906144e8565b9050804210156138085760405162461bcd60e51b815260206004820152601c60248201527f4c494d49545f4f524445525f545249474745525f544f4f5f534f4f4e000000006044820152606401610ad4565b808210156138645760405162461bcd60e51b815260206004820152602360248201527f4c494d49545f4f524445525f50524943455f4f55545f4f465f54494d455f4652604482015262414d4560e81b6064820152608401610ad4565b610dae82600c54613efa565b6000620186a08363ffffffff1611156138cb5760405162461bcd60e51b815260206004820152601960248201527f5350524541445f524544554354494f4e5f544f4f5f48494748000000000000006044820152606401610ad4565b600085815260056020526040812054620186a0906138f9906001600160401b0388169063ffffffff16614674565b613903919061468b565b90506000620186a061391b63ffffffff8716846146ad565b6001600160401b031661392e919061468b565b61393890836146d8565b90508361394e5761394981876146d8565b613958565b61395881876146f8565b979650505050505050565b60405163c07f992160e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c07f9921906139b8908990889088908890600401614718565b600060405180830381600087803b1580156139d257600080fd5b505af19250505080156139e3575060015b613bde576139ef614728565b806308c379a003613a755750613a03614744565b80613a0e5750613a77565b856003811115613a2057613a206143c4565b87896001600160a01b03167f889460050d9a293fbe31b6ce00a37ae62020cb8c8a19cf31e9496cb13246f6e2888888876000604051613a639594939291906147cd565b60405180910390a46000915050613c3a565b505b3d808015613aa1576040519150601f19603f3d011682016040523d82523d6000602084013e613aa6565b606091505b50632eb752bf60e21b613ab88261484f565b6001600160e01b03191603613b9f576001856002811115613adb57613adb6143c4565b14613b1e5760405162461bcd60e51b815260206004820152601360248201527204341505f4552524f525f4e4f545f4f4e5f545606c1b6044820152606401610ad4565b60248101516044820151876003811115613b3a57613b3a6143c4565b898b6001600160a01b03167f889460050d9a293fbe31b6ce00a37ae62020cb8c8a19cf31e9496cb13246f6e28a8a8a886011811115613b7b57613b7b6143c4565b604051613b8b9493929190614886565b60405180910390a460009350505050613c3a565b60405162461bcd60e51b81526020600482015260146024820152732aa725a727aba72fa1aaa9aa27a6afa2a92927a960611b6044820152606401610ad4565b846003811115613bf057613bf06143c4565b86886001600160a01b03167ff0ac91a20375484f5a80315763782e4fe4b42bd038b08ba4939ff1a506974edf878787604051613c2e939291906148d5565b60405180910390a45060015b9695505050505050565b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161115613cba5760405162461bcd60e51b815260206004820152601c60248201527f434f4e464944454e43455f4652414354494f4e5f544f4f5f48494748000000006044820152606401610ad4565b600082815260046020908152604091829020805463ffffffff191663ffffffff8516908117909155915191825283917f88e6fad616d859d6fba20e93ab2acbf0756b6bc2d90c6002000f709f510cadb09101613775565b6060600061379f83613f88565b613d2781610f1e565b613d695760405162461bcd60e51b81526020600482015260136024820152721050d0d3d5539517d393d517d0531313d5d151606a1b6044820152606401610ad4565b613d74600282613fe4565b506040516001600160a01b038216907fc985d67a353004ba149a223b2b9e5c13cca6610b11cb45b4aa029c880d8f7cb590600090a250565b613db581610f1e565b15613e025760405162461bcd60e51b815260206004820152601760248201527f4143434f554e545f414c52454144595f414c4c4f5745440000000000000000006044820152606401610ad4565b613e0d600282613ff9565b506040516001600160a01b038216907fc5944eab072face4b169928723314c5978080e99ed8f8527faedb18c06664c3590600090a250565b6040805160608101825260008082526020820181905281830152600654915163f4a6a09360e01b815290916001600160a01b03169063f4a6a093908690613e9490899088908890600401614929565b60606040518083038185885af1158015613eb2573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613ed791906149d1565b95945050505050565b6000620186a0613ef08385614674565b61379f919061468b565b6000613f068242614a43565b905080831015613f485760405162461bcd60e51b815260206004820152600d60248201526c14149250d157d513d3d7d3d311609a1b6044820152606401610ad4565b42831115610dae5760405162461bcd60e51b815260206004820152600d60248201526c50524943455f544f4f5f4e455760981b6044820152606401610ad4565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fd857602002820191906000526020600020905b815481526020019060010190808311613fc4575b50505050509050919050565b600061379f836001600160a01b03841661400e565b600061379f836001600160a01b038416614108565b600081815260018301602052604081205480156140f7576000614032600183614a43565b855490915060009061404690600190614a43565b90508082146140ab57600086600001828154811061406657614066614a56565b906000526020600020015490508087600001848154811061408957614089614a56565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806140bc576140bc614a6c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f2b565b6000915050610f2b565b5092915050565b600081815260018301602052604081205461414f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f2b565b506000610f2b565b60006020828403121561416957600080fd5b5035919050565b60008083601f84011261418257600080fd5b5081356001600160401b0381111561419957600080fd5b6020830191508360208260051b85010111156141b457600080fd5b9250929050565b6000806000604084860312156141d057600080fd5b8335925060208401356001600160401b038111156141ed57600080fd5b6141f986828701614170565b9497909650939450505050565b63ffffffff811681146110e557600080fd5b6000806040838503121561422b57600080fd5b82359150602083013561423d81614206565b809150509250929050565b60006020828403121561425a57600080fd5b81356001600160a01b038116811461379f57600080fd5b6020808252825182820181905260009190848201906040850190845b818110156134af5783516001600160a01b03168352928401929184019160010161428d565b602080825260049082015263444f4e4560e01b604082015260600190565b60208082526006908201526514105554d15160d21b604082015260600190565b6020808252601690820152752727aa2fa0a62627aba2a22faa27afaa2924a3a3a2a960511b604082015260600190565b80516001600160401b038116811461433757600080fd5b919050565b8051801515811461433757600080fd5b600080600080600060a0868803121561436457600080fd5b85516006811061437357600080fd5b945061438160208701614320565b9350604086015161ffff8116811461439857600080fd5b92506143a66060870161433c565b915060808601516143b681614206565b809150509295509295909350565b634e487b7160e01b600052602160045260246000fd5b6020808252600a908201526927a7262cafa0a226a4a760b11b604082015260600190565b601f8201601f191681016001600160401b038111828210171561443157634e487b7160e01b600052604160045260246000fd5b6040525050565b600060a0828403121561444a57600080fd5b60405160a081018181106001600160401b038211171561447a57634e487b7160e01b600052604160045260246000fd5b6040528251815260208301516004811061449357600080fd5b60208201526144a460408401614320565b60408201526144b560608401614320565b60608201526144c660808401614320565b60808201529392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f2b57610f2b6144d2565b6020808252600c908201526b15d0525517d512535153d55560a21b604082015260600190565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b8381526060810160028410614562576145626143c4565b602082019390935260400152919050565b60006080828403121561458557600080fd5b604051608081018181106001600160401b03821117156145b557634e487b7160e01b600052604160045260246000fd5b6040526145c183614320565b81526145cf60208401614320565b60208201526145e060408401614320565b60408201526145f160608401614320565b60608201529392505050565b8481526080810160048510614614576146146143c4565b60208201949094526001600160401b0392831660408201529116606090910152919050565b600381106110e5576110e56143c4565b8381526060810161456284614639565b60006020828403121561466b57600080fd5b61379f8261433c565b8082028115828204841417610f2b57610f2b6144d2565b6000826146a857634e487b7160e01b600052601260045260246000fd5b500490565b6001600160401b038181168382160280821691908281146146d0576146d06144d2565b505092915050565b6001600160401b03828116828216039080821115614101576141016144d2565b6001600160401b03818116838216019080821115614101576141016144d2565b8481526080810161461485614639565b600060033d11156147415760046000803e5060005160e01c5b90565b600060443d10156147525790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561478157505050505090565b82850191508151818111156147995750505050505090565b843d87010160208285010111156147b35750505050505090565b6147c2602082860101876143fe565b509095945050505050565b6147d686614639565b858152600060206001600160401b03808816602085015280871660408501525060a0606084015284518060a085015260005b818110156148245786810183015185820160c001528201614808565b50600060c0828601015260c0601f19601f830116850101925050508260808301529695505050505050565b805160208201516001600160e01b0319808216929190600483101561487e5780818460040360031b1b83161693505b505050919050565b61488f85614639565b9384526001600160401b0392831660208501529116604083015260a0606083018190526009908301526821a0a82fa2a92927a960b91b60c0830152608082015260e00190565b606081016148e285614639565b9381526001600160401b039283166020820152911660409091015290565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000604082018583526020604060208501528185835260608501905060608660051b86010192508660005b878110156149c357868503605f190183528135368a9003601e1901811261497a57600080fd5b890184810190356001600160401b0381111561499557600080fd5b8036038213156149a457600080fd5b6149af878284614900565b965050509183019190830190600101614954565b509298975050505050505050565b6000606082840312156149e357600080fd5b604051606081018181106001600160401b0382111715614a1357634e487b7160e01b600052604160045260246000fd5b60405282518152614a2660208401614320565b6020820152614a3760408401614320565b60408201529392505050565b81810381811115610f2b57610f2b6144d2565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212205ea30faf884e26d1e90ed9111c8ccbd84fa172559deb1ea27cff51bc6487b13c64736f6c6343000818003300000000000000000000000037792eecfa985d0b00a51864c970e7df406aa868

Deployed Bytecode

0x6080604052600436106103815760003560e01c8063776af5ba116101d1578063ad1f2b5611610102578063c4ae3168116100a0578063e9c714f21161006f578063e9c714f214610a37578063f851a44014610a4c578063fae5a83f14610a6c578063fd057e9414610a8c57600080fd5b8063c4ae3168146109cf578063d99dc0c1146109e4578063e231377014610a04578063e8051b0114610a2457600080fd5b8063b71f3cfe116100dc578063b71f3cfe14610943578063b81bfa051461095b578063b88750a91461097b578063bfc084d9146109af57600080fd5b8063ad1f2b56146108f4578063b187bd2614610909578063b71d1a0c1461092357600080fd5b80639abf17821161016f578063a5b6020811610149578063a5b602081461088f578063a5e02c8d146108a5578063a9f7c521146108c5578063aaf5eb68146108d857600080fd5b80639abf17821461081c5780639f918f451461083c578063a1d627a11461086f57600080fd5b806380193b26116101ab57806380193b26146107ae57806381405205146107c557806386c7f19a146107db5780638f062227146107fd57600080fd5b8063776af5ba1461074e5780637f31c2db146107825780637f588b911461079857600080fd5b8063392503e0116102b65780634cdb06a5116102545780636c1bb5ca116102235780636c1bb5ca146106e8578063718ddc14146107085780637670d9481461071b578063771ad70d1461073b57600080fd5b80634cdb06a51461065a5780634d3691511461067a5780635d2cdfea1461068d5780636447dc8b146106d557600080fd5b8063410c0b7c11610290578063410c0b7c146105fb57806345b6171314610611578063490580e3146106275780634bdf19731461064757600080fd5b8063392503e0146105bd5780633b321666146105d35780633be3d626146105e657600080fd5b806326b4120a1161032357806333a01d32116102fd57806333a01d321461050357806336930d0b1461053757806336b669f714610557578063382672571461059d57600080fd5b806326b4120a146104935780632f86d7c2146104b357806333511e5e146104d357600080fd5b8063221407af1161035f578063221407af1461042857806322ede93c1461043d57806325577e9f14610453578063267822471461047357600080fd5b80630d3b0b761461038657806310b4cc13146103d757806320cb5976146103fb575b600080fd5b34801561039257600080fd5b506103ba7f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa86881565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103e357600080fd5b506103ed600d5481565b6040519081526020016103ce565b34801561040757600080fd5b506103ed610416366004614157565b60106020526000908152604090205481565b61043b6104363660046141bb565b610aac565b005b34801561044957600080fd5b506103ed600e5481565b34801561045f57600080fd5b5061043b61046e366004614218565b610db3565b34801561047f57600080fd5b506001546103ba906001600160a01b031681565b34801561049f57600080fd5b5061043b6104ae366004614157565b610deb565b3480156104bf57600080fd5b5061043b6104ce366004614157565b610e82565b3480156104df57600080fd5b506104f36104ee366004614248565b610f1e565b60405190151581526020016103ce565b34801561050f57600080fd5b506103ed7f00000000000000000000000000000000000000000000000000000000000003e881565b34801561054357600080fd5b5061043b610552366004614157565b610f31565b61056a6105653660046141bb565b6110e8565b60408051825181526020808401516001600160401b039081169183019190915292820151909216908201526060016103ce565b3480156105a957600080fd5b5061043b6105b8366004614157565b611119565b3480156105c957600080fd5b506103ed600c5481565b61043b6105e13660046141bb565b611399565b3480156105f257600080fd5b5061043b6116a7565b34801561060757600080fd5b506103ed600a5481565b34801561061d57600080fd5b506103ed60075481565b34801561063357600080fd5b5061043b610642366004614157565b611733565b61043b6106553660046141bb565b611786565b34801561066657600080fd5b5061043b610675366004614157565b611abd565b61043b6106883660046141bb565b611b26565b34801561069957600080fd5b506106c06106a8366004614157565b60056020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016103ce565b61043b6106e33660046141bb565b611d7f565b3480156106f457600080fd5b5061043b610703366004614218565b6120a2565b61043b6107163660046141bb565b6120d6565b34801561072757600080fd5b5061043b610736366004614157565b61233f565b61043b6107493660046141bb565b61239c565b34801561075a57600080fd5b506103ba7f00000000000000000000000008422b1ca26c4b6e28bd8635cabb03bc1dbe5d6281565b34801561078e57600080fd5b506103ed60085481565b3480156107a457600080fd5b506103ed60095481565b3480156107ba57600080fd5b506103ed620186a081565b3480156107d157600080fd5b506103ed600f5481565b3480156107e757600080fd5b506107f06125de565b6040516103ce9190614271565b34801561080957600080fd5b506011546104f390610100900460ff1681565b34801561082857600080fd5b5061043b610837366004614157565b6125ef565b34801561084857600080fd5b506106c0610857366004614157565b60046020526000908152604090205463ffffffff1681565b34801561087b57600080fd5b506006546103ba906001600160a01b031681565b34801561089b57600080fd5b506103ed600b5481565b3480156108b157600080fd5b5061043b6108c0366004614248565b61264c565b61043b6108d33660046141bb565b61267f565b3480156108e457600080fd5b506103ed670de0b6b3a764000081565b34801561090057600080fd5b506103ed606481565b34801561091557600080fd5b506011546104f39060ff1681565b34801561092f57600080fd5b5061043b61093e366004614248565b6128cb565b34801561094f57600080fd5b506103ed633b9aca0081565b34801561096757600080fd5b5061043b610976366004614157565b612973565b34801561098757600080fd5b506103ed7f000000000000000000000000000000000000000000000000000000000000271081565b3480156109bb57600080fd5b5061043b6109ca366004614157565b6129c6565b3480156109db57600080fd5b5061043b612a23565b3480156109f057600080fd5b5061043b6109ff366004614248565b612a95565b348015610a1057600080fd5b5061043b610a1f366004614157565b612ac8565b61043b610a323660046141bb565b612d47565b348015610a4357600080fd5b5061043b61303e565b348015610a5857600080fd5b506000546103ba906001600160a01b031681565b348015610a7857600080fd5b5061043b610a87366004614248565b61315c565b348015610a9857600080fd5b5061043b610aa7366004614157565b61329b565b601154610100900460ff1615610add5760405162461bcd60e51b8152600401610ad4906142b2565b60405180910390fd5b60115460ff1615610b005760405162461bcd60e51b8152600401610ad4906142d0565b610b0933610f1e565b610b255760405162461bcd60e51b8152600401610ad4906142f0565b610b2d613337565b60008060007f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03166395be5050876040518263ffffffff1660e01b8152600401610b8091815260200190565b60a060405180830381865afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc1919061434c565b505092506001600160401b03169250925060008211610c1c5760405162461bcd60e51b81526020600482015260176024820152762727afa822a72224a723afa6a0a925a2aa2fa7a92222a960491b6044820152606401610ad4565b6004836005811115610c3057610c306143c4565b14610c705760405162461bcd60e51b815260206004820152601060248201526f1393d517d0d313d4d157d3505492d15560821b6044820152606401610ad4565b6000610c828261ffff163488886133ac565b9050610c928382600001516134bb565b602081015180610ca06135e7565b602083015160405163651d1d4160e11b8152600481018b90526001600160401b03918216602482015290821660448201527f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03169063ca3a3a8290606401600060405180830381600087803b158015610d1f57600080fd5b505af1158015610d33573d6000803e3d6000fd5b50505050856005811115610d4957610d496143c4565b6020848101518551604080516001600160401b038781168252909316938301939093528183015290518b9133917f5b5ec0827d50049e9f15c1d5c28dc87d620987ef82a18f0b98afac1c76076d3d9181900360600190a4505050505050610dae61365f565b505050565b6000546001600160a01b03163314610ddd5760405162461bcd60e51b8152600401610ad4906143da565b610de782826136ba565b5050565b6000546001600160a01b03163314610e155760405162461bcd60e51b8152600401610ad4906143da565b600b8190556040517f6d61726b65744f72646572546967687454696d6552616e67650000000000000081526019015b604051908190038120828252907f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab906020015b60405180910390a250565b6000546001600160a01b03163314610eac5760405162461bcd60e51b8152600401610ad4906143da565b6008548110610eeb5760405162461bcd60e51b815260206004820152600b60248201526a57524f4e475f56414c554560a81b6044820152606401610ad4565b60078190556040517f6d696e54726967676572506572696f64466f724d61726b65744f7264657273008152601f01610e44565b6000610f2b600283613781565b92915050565b601154610100900460ff1615610f595760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615610f7c5760405162461bcd60e51b8152600401610ad4906142d0565b610f8533610f1e565b610fa15760405162461bcd60e51b8152600401610ad4906142f0565b610fa9613337565b60405163c608b6c160e01b8152600481018290526000907f00000000000000000000000008422b1ca26c4b6e28bd8635cabb03bc1dbe5d626001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190614438565b9050600a5481604001516001600160401b031661105491906144e8565b4210156110735760405162461bcd60e51b8152600401610ad4906144fb565b80602001516003811115611089576110896143c4565b60608201516080830151604080516001600160401b039384168152929091166020830152849133917f7b5b2e57aed6ee99244bd22f2b43e33e9fcbf0d77a9f425d59ee2d74e1c3795d910160405180910390a4506110e561365f565b50565b6040805160608101825260008082526020820181905291810191909152611111843485856133ac565b949350505050565b601154610100900460ff16156111415760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156111645760405162461bcd60e51b8152600401610ad4906142d0565b61116d33610f1e565b6111895760405162461bcd60e51b8152600401610ad4906142f0565b611191613337565b60008060007f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03166395be5050856040518263ffffffff1660e01b81526004016111e491815260200190565b60a060405180830381865afa158015611201573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611225919061434c565b505092506001600160401b031692509250600082116112565760405162461bcd60e51b8152600401610ad490614521565b600483600581111561126a5761126a6143c4565b146112aa5760405162461bcd60e51b815260206004820152601060248201526f1393d517d0d313d4d157d3505492d15560821b6044820152606401610ad4565b600a546112b790836144e8565b4210156112d65760405162461bcd60e51b8152600401610ad4906144fb565b600d54604051634ebe5c3360e01b81526001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8681691634ebe5c33916113299188916001919060040161454b565b600060405180830381600087803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b505060405161ffff8416925086915033907f89a3ecf5024675f1d0abc6dc42608fc41216f103c12c2c84f8ca3938bd055f0390600090a45050506110e561365f565b601154610100900460ff16156113c15760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156113e45760405162461bcd60e51b8152600401610ad4906142d0565b6113ed33610f1e565b6114095760405162461bcd60e51b8152600401610ad4906142f0565b611411613337565b60008060008060007f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03166395be5050896040518263ffffffff1660e01b815260040161146791815260200190565b60a060405180830381865afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a8919061434c565b9450945094506001600160401b031694509450600084116115045760405162461bcd60e51b81526020600482015260166024820152752727afa822a72224a723afa624a6a4aa2fa7a92222a960511b6044820152606401610ad4565b6002856005811115611518576115186143c4565b146115565760405162461bcd60e51b815260206004820152600e60248201526d1393d517d3d4115397d31253525560921b6044820152606401610ad4565b60006115688461ffff16348a8a6133ac565b90506115788582600001516137a6565b6020810151600061158f61ffff8716838688613870565b90506115996135e7565b600e54604051631ea9af6b60e01b8152600481018d90526001600160401b038316602482015260448101919091527f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b031690631ea9af6b906064015b600060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b50505050876005811115611640576116406143c4565b6020848101518551604080516001600160401b038781168252909316938301939093528183015290518d9133917f60fab6e183a7c350210c0b457db01423b47aa3e72f5b735b8dbb3ecd3e8077439181900360600190a45050505050505050610dae61365f565b6000546001600160a01b031633146116d15760405162461bcd60e51b8152600401610ad4906143da565b6011805460ff610100808304821615810261ff001990931692909217928390556040517f8e47bd62470c6cba4d30c023548622607c9c84402a5655f2569b7934c36a9e4f936117299390049091161515815260200190565b60405180910390a1565b6000546001600160a01b0316331461175d5760405162461bcd60e51b8152600401610ad4906143da565b600f819055604051726d61785472696767657273506572426c6f636b60681b8152601301610e44565b601154610100900460ff16156117ae5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156117d15760405162461bcd60e51b8152600401610ad4906142d0565b6117da33610f1e565b6117f65760405162461bcd60e51b8152600401610ad4906142f0565b6117fe613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa158015611866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188a919061434c565b50506040516366307a4f60e01b815260048101889052909350600092506001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8681691506366307a4f90602401608060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190614573565b905060008261ffff16116119435760405162461bcd60e51b8152600401610ad490614521565b600081606001516001600160401b0316116119885760405162461bcd60e51b81526020600482015260056024820152641393d7d4d360da1b6044820152606401610ad4565b60208101516001600160401b031660006119a861ffff85163488886133ac565b90506119b88282600001516137a6565b60208101516119c56135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa86816916380a7f3d491611a1c918c916002919087906004016145fd565b600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b5050506020808401518451604080516001600160401b038088168252909316938301939093529181019190915261ffff87169150899033907fb03dbc9368faf0f8588dc8429c40a26ef9a637488f1ea5521a2ba2bfb5ff2016906060015b60405180910390a45050505050610dae61365f565b6000546001600160a01b03163314611ae75760405162461bcd60e51b8152600401610ad4906143da565b600e8190556040517f6f70656e506f736974696f6e43616e63656c6c6174696f6e466565467261637481526234b7b760e91b6020820152602301610e44565b601154610100900460ff1615611b4e5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615611b715760405162461bcd60e51b8152600401610ad4906142d0565b611b7a33610f1e565b611b965760405162461bcd60e51b8152600401610ad4906142f0565b611b9e613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000008422b1ca26c4b6e28bd8635cabb03bc1dbe5d626001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015611c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2c9190614438565b9050600281602001516003811115611c4657611c466143c4565b14611c895760405162461bcd60e51b815260206004820152601360248201527215541110551157d3d491115497d393d517d4d3606a1b6044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa158015611cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d15919061434c565b5050925050506000611d2d8261ffff163487876133ac565b9050611d4a83604001516001600160401b031682600001516134bb565b611d526135e7565b600081602001519050611d72338886602001516002886060015186613963565b5050505050610dae61365f565b601154610100900460ff1615611da75760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615611dca5760405162461bcd60e51b8152600401610ad4906142d0565b611dd333610f1e565b611def5760405162461bcd60e51b8152600401610ad4906142f0565b611df7613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e83919061434c565b50506040516366307a4f60e01b815260048101889052909350600092506001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8681691506366307a4f90602401608060405180830381865afa158015611ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f169190614573565b905060008261ffff1611611f3c5760405162461bcd60e51b8152600401610ad490614521565b600081604001516001600160401b031611611f815760405162461bcd60e51b815260206004820152600560248201526404e4f5f54560dc1b6044820152606401610ad4565b80516001600160401b03166000611f9e61ffff85163488886133ac565b9050611fae8282600001516137a6565b6020810151611fbb6135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa86816916380a7f3d491612012918c916001919087906004016145fd565b600060405180830381600087803b15801561202c57600080fd5b505af1158015612040573d6000803e3d6000fd5b5050506020808401518451604080516001600160401b038088168252909316938301939093529181019190915261ffff87169150899033907fbe700227f721a08f3b755aa3348a63564c2c07890aba73de46372f7bffcaa2e290606001611aa8565b6000546001600160a01b031633146120cc5760405162461bcd60e51b8152600401610ad4906143da565b610de78282613c44565b601154610100900460ff16156120fe5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156121215760405162461bcd60e51b8152600401610ad4906142d0565b61212a33610f1e565b6121465760405162461bcd60e51b8152600401610ad4906142f0565b61214e613337565b60008060008060007f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03166395be5050896040518263ffffffff1660e01b81526004016121a491815260200190565b60a060405180830381865afa1580156121c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e5919061434c565b9450945094506001600160401b031694509450600084116122425760405162461bcd60e51b81526020600482015260176024820152762727afa822a72224a723afa6a0a925a2aa2fa7a92222a960491b6044820152606401610ad4565b6001856005811115612256576122566143c4565b146122955760405162461bcd60e51b815260206004820152600f60248201526e1393d517d3d4115397d3505492d155608a1b6044820152606401610ad4565b60006122a78461ffff16348a8a6133ac565b90506122b78582600001516134bb565b602081015160006122ce61ffff8716838688613870565b90506122d86135e7565b600e546040516303ad224560e61b8152600481018d90526001600160401b038316602482015260448101919091527f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03169063eb489140906064016115fc565b6000546001600160a01b031633146123695760405162461bcd60e51b8152600401610ad4906143da565b600c8190556040517f74726967676572507269636546726573686e65737354696d6552616e676500008152601e01610e44565b601154610100900460ff16156123c45760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156123e75760405162461bcd60e51b8152600401610ad4906142d0565b6123f033610f1e565b61240c5760405162461bcd60e51b8152600401610ad4906142f0565b612414613337565b60405163095be50560e41b8152600481018490526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa15801561247c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a0919061434c565b50509250505060008161ffff16116124ca5760405162461bcd60e51b8152600401610ad490614521565b60006124dc8261ffff163486866133ac565b60208101519091506124ec6135e7565b6020820151604051632029fcf560e21b81526001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa86816916380a7f3d491612543918a916003919087906004016145fd565b600060405180830381600087803b15801561255d57600080fd5b505af1158015612571573d6000803e3d6000fd5b505050506020828101518351604080516001600160401b0386811682529093169383019390935281830152905161ffff851691889133917f086bdd0cdd4ae322dd6112d05bdf96c020e6b90cc84ee2d39941bd716e18fb92919081900360600190a4505050610dae61365f565b60606125ea6002613d11565b905090565b6000546001600160a01b031633146126195760405162461bcd60e51b8152600401610ad4906143da565b600d8190556040517f6d61726b65744f7264657243616e63656c4665654672616374696f6e000000008152601c01610e44565b6000546001600160a01b031633146126765760405162461bcd60e51b8152600401610ad4906143da565b6110e581613d1e565b601154610100900460ff16156126a75760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff16156126ca5760405162461bcd60e51b8152600401610ad4906142d0565b6126d333610f1e565b6126ef5760405162461bcd60e51b8152600401610ad4906142f0565b6126f7613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000008422b1ca26c4b6e28bd8635cabb03bc1dbe5d626001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015612761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127859190614438565b905060018160200151600381111561279f5761279f6143c4565b146127e25760405162461bcd60e51b815260206004820152601360248201527205550444154455f4f524445525f4e4f545f545606c1b6044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa15801561284a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286e919061434c565b50509250505060006128868261ffff163487876133ac565b90506128a383604001516001600160401b031682600001516134bb565b6128ab6135e7565b600081602001519050611d72338886602001516001886060015186613963565b6000546001600160a01b031633146129115760405162461bcd60e51b81526020600482015260096024820152682737ba1020b236b4b760b91b6044820152606401610ad4565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a991015b60405180910390a15050565b6000546001600160a01b0316331461299d5760405162461bcd60e51b8152600401610ad4906143da565b600a819055604051721b585c9ad95d13dc99195c9cd51a5b595bdd5d606a1b8152601301610e44565b6000546001600160a01b031633146129f05760405162461bcd60e51b8152600401610ad4906143da565b60098190556040517f6d696e54726967676572506572696f64466f724c696d69744f726465727300008152601e01610e44565b6000546001600160a01b03163314612a4d5760405162461bcd60e51b8152600401610ad4906143da565b6011805460ff8082161560ff1990921682179092556040519116151581527fda88b5dfaac55549d4ddddd43a09d4b911233df354952ebc9ac2041aa185343690602001611729565b6000546001600160a01b03163314612abf5760405162461bcd60e51b8152600401610ad4906143da565b6110e581613dac565b601154610100900460ff1615612af05760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615612b135760405162461bcd60e51b8152600401610ad4906142d0565b612b1c33610f1e565b612b385760405162461bcd60e51b8152600401610ad4906142f0565b612b40613337565b60008060007f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b03166395be5050856040518263ffffffff1660e01b8152600401612b9391815260200190565b60a060405180830381865afa158015612bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd4919061434c565b505092506001600160401b03169250925060008211612c055760405162461bcd60e51b8152600401610ad490614521565b6001836005811115612c1957612c196143c4565b14612c585760405162461bcd60e51b815260206004820152600f60248201526e1393d517d3d4115397d3505492d155608a1b6044820152606401610ad4565b600a54612c6590836144e8565b421015612c845760405162461bcd60e51b8152600401610ad4906144fb565b600d54604051636e01af8d60e01b81526001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8681691636e01af8d91612cd791889160019190600401614649565b600060405180830381600087803b158015612cf157600080fd5b505af1158015612d05573d6000803e3d6000fd5b505060405161ffff8416925086915033907f5079795ec65f793d5a0ed74d8f8e1562b7795934b40612bf55cf0e5d55a3447990600090a45050506110e561365f565b601154610100900460ff1615612d6f5760405162461bcd60e51b8152600401610ad4906142b2565b60115460ff1615612d925760405162461bcd60e51b8152600401610ad4906142d0565b612d9b33610f1e565b612db75760405162461bcd60e51b8152600401610ad4906142f0565b612dbf613337565b60405163c608b6c160e01b8152600481018490526000907f00000000000000000000000008422b1ca26c4b6e28bd8635cabb03bc1dbe5d626001600160a01b03169063c608b6c19060240160a0604051808303816000875af1158015612e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4d9190614438565b9050600381602001516003811115612e6757612e676143c4565b14612eb45760405162461bcd60e51b815260206004820152601a60248201527f5550444154455f4f524445525f4e4f545f54505f414e445f534c0000000000006044820152606401610ad4565b60405163095be50560e41b8152600481018590526000907f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa8686001600160a01b0316906395be50509060240160a060405180830381865afa158015612f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f40919061434c565b5050925050506000612f588261ffff163487876133ac565b9050612f7583604001516001600160401b031682600001516134bb565b612f7d6135e7565b600081602001519050612f9d338886602001516001886060015186613963565b612fdc5760405162461bcd60e51b815260206004820152601060248201526f4641494c45445f54505f55504441544560801b6044820152606401610ad4565b612ff3338886602001516002886080015186613963565b6130325760405162461bcd60e51b815260206004820152601060248201526f4641494c45445f534c5f55504441544560801b6044820152606401610ad4565b50505050610dae61365f565b6001546001600160a01b03163314801561306257506001546001600160a01b031615155b6130ae5760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420746865204558495354494e472070656e64696e672061646d696e00006044820152606401610ad4565b60008054600180546001600160a01b038082166001600160a01b031980861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101612967565b6000546001600160a01b031633146131865760405162461bcd60e51b8152600401610ad4906143da565b806001600160a01b0316634535dc4c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e89190614659565b6132265760405162461bcd60e51b815260206004820152600f60248201526e10a83934b1b2ab30b634b230ba37b960891b6044820152606401610ad4565b600680546001600160a01b0319166001600160a01b0383161790556040516d283934b1b2ab30b634b230ba37b960911b8152600e016040519081900381206001600160a01b0383168252907f943e9d45a11aaae5d87503e3bc248665d9807856e5cf2bdb4a988bee4442278190602001610e77565b6000546001600160a01b031633146132c55760405162461bcd60e51b8152600401610ad4906143da565b60075481116133045760405162461bcd60e51b815260206004820152600b60248201526a57524f4e475f56414c554560a81b6044820152606401610ad4565b60088190556040517f6d617854726967676572506572696f64466f724d61726b65744f7264657273008152601f01610e44565b7f0000000000000000000000004cf3d61165a6be8ff741320ad27cab57fae5c2076001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561339257600080fd5b505af11580156133a6573d6000803e3d6000fd5b50505050565b60408051606081018252600080825260208201819052918101829052906133d586868686613e45565b60008781526004602090815260408220549083015192935063ffffffff1691613407906001600160401b031683613ee0565b90508083604001516001600160401b031611156134665760405162461bcd60e51b815260206004820152601960248201527f434f4e464944454e43455f52414e47455f544f4f5f57494445000000000000006044820152606401610ad4565b82514210156134af5760405162461bcd60e51b815260206004820152601560248201527411955515549157d4149250d157d4915413d4951151605a1b6044820152606401610ad4565b50909695505050505050565b6000600754836134cb91906144e8565b90506000600854846134dd91906144e8565b90508142101561352f5760405162461bcd60e51b815260206004820152601d60248201527f4d41524b45545f4f524445525f545249474745525f544f4f5f534f4f4e0000006044820152606401610ad4565b8042111561357f5760405162461bcd60e51b815260206004820152601d60248201527f4d41524b45545f4f524445525f545249474745525f544f4f5f4c4154450000006044820152606401610ad4565b81831015801561358f5750808311155b6133a65760405162461bcd60e51b8152602060048201526024808201527f4d41524b45545f4f524445525f50524943455f4f55545f4f465f54494d455f4660448201526352414d4560e01b6064820152608401610ad4565b43600090815260106020526040902054600f5481106136415760405162461bcd60e51b81526020600482015260166024820152754d41585f54524947474552535f5045525f424c4f434b60501b6044820152606401610ad4565b61364c8160016144e8565b4360009081526010602052604090205550565b7f0000000000000000000000004cf3d61165a6be8ff741320ad27cab57fae5c2076001600160a01b03166340da020f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561339257600080fd5b7f00000000000000000000000000000000000000000000000000000000000003e88163ffffffff1611156137225760405162461bcd60e51b815260206004820152600f60248201526e0a6a0a48a8288bea89e9ebe90928e9608b1b6044820152606401610ad4565b600082815260056020908152604091829020805463ffffffff191663ffffffff8516908117909155915191825283917ffe5fd0852fab5f8ba593533cf24a4b4b235704c0e06956d0a58cc2ca0a4b6b4491015b60405180910390a25050565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000600954836137b691906144e8565b9050804210156138085760405162461bcd60e51b815260206004820152601c60248201527f4c494d49545f4f524445525f545249474745525f544f4f5f534f4f4e000000006044820152606401610ad4565b808210156138645760405162461bcd60e51b815260206004820152602360248201527f4c494d49545f4f524445525f50524943455f4f55545f4f465f54494d455f4652604482015262414d4560e81b6064820152608401610ad4565b610dae82600c54613efa565b6000620186a08363ffffffff1611156138cb5760405162461bcd60e51b815260206004820152601960248201527f5350524541445f524544554354494f4e5f544f4f5f48494748000000000000006044820152606401610ad4565b600085815260056020526040812054620186a0906138f9906001600160401b0388169063ffffffff16614674565b613903919061468b565b90506000620186a061391b63ffffffff8716846146ad565b6001600160401b031661392e919061468b565b61393890836146d8565b90508361394e5761394981876146d8565b613958565b61395881876146f8565b979650505050505050565b60405163c07f992160e01b81526000906001600160a01b037f00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa868169063c07f9921906139b8908990889088908890600401614718565b600060405180830381600087803b1580156139d257600080fd5b505af19250505080156139e3575060015b613bde576139ef614728565b806308c379a003613a755750613a03614744565b80613a0e5750613a77565b856003811115613a2057613a206143c4565b87896001600160a01b03167f889460050d9a293fbe31b6ce00a37ae62020cb8c8a19cf31e9496cb13246f6e2888888876000604051613a639594939291906147cd565b60405180910390a46000915050613c3a565b505b3d808015613aa1576040519150601f19603f3d011682016040523d82523d6000602084013e613aa6565b606091505b50632eb752bf60e21b613ab88261484f565b6001600160e01b03191603613b9f576001856002811115613adb57613adb6143c4565b14613b1e5760405162461bcd60e51b815260206004820152601360248201527204341505f4552524f525f4e4f545f4f4e5f545606c1b6044820152606401610ad4565b60248101516044820151876003811115613b3a57613b3a6143c4565b898b6001600160a01b03167f889460050d9a293fbe31b6ce00a37ae62020cb8c8a19cf31e9496cb13246f6e28a8a8a886011811115613b7b57613b7b6143c4565b604051613b8b9493929190614886565b60405180910390a460009350505050613c3a565b60405162461bcd60e51b81526020600482015260146024820152732aa725a727aba72fa1aaa9aa27a6afa2a92927a960611b6044820152606401610ad4565b846003811115613bf057613bf06143c4565b86886001600160a01b03167ff0ac91a20375484f5a80315763782e4fe4b42bd038b08ba4939ff1a506974edf878787604051613c2e939291906148d5565b60405180910390a45060015b9695505050505050565b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161115613cba5760405162461bcd60e51b815260206004820152601c60248201527f434f4e464944454e43455f4652414354494f4e5f544f4f5f48494748000000006044820152606401610ad4565b600082815260046020908152604091829020805463ffffffff191663ffffffff8516908117909155915191825283917f88e6fad616d859d6fba20e93ab2acbf0756b6bc2d90c6002000f709f510cadb09101613775565b6060600061379f83613f88565b613d2781610f1e565b613d695760405162461bcd60e51b81526020600482015260136024820152721050d0d3d5539517d393d517d0531313d5d151606a1b6044820152606401610ad4565b613d74600282613fe4565b506040516001600160a01b038216907fc985d67a353004ba149a223b2b9e5c13cca6610b11cb45b4aa029c880d8f7cb590600090a250565b613db581610f1e565b15613e025760405162461bcd60e51b815260206004820152601760248201527f4143434f554e545f414c52454144595f414c4c4f5745440000000000000000006044820152606401610ad4565b613e0d600282613ff9565b506040516001600160a01b038216907fc5944eab072face4b169928723314c5978080e99ed8f8527faedb18c06664c3590600090a250565b6040805160608101825260008082526020820181905281830152600654915163f4a6a09360e01b815290916001600160a01b03169063f4a6a093908690613e9490899088908890600401614929565b60606040518083038185885af1158015613eb2573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613ed791906149d1565b95945050505050565b6000620186a0613ef08385614674565b61379f919061468b565b6000613f068242614a43565b905080831015613f485760405162461bcd60e51b815260206004820152600d60248201526c14149250d157d513d3d7d3d311609a1b6044820152606401610ad4565b42831115610dae5760405162461bcd60e51b815260206004820152600d60248201526c50524943455f544f4f5f4e455760981b6044820152606401610ad4565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fd857602002820191906000526020600020905b815481526020019060010190808311613fc4575b50505050509050919050565b600061379f836001600160a01b03841661400e565b600061379f836001600160a01b038416614108565b600081815260018301602052604081205480156140f7576000614032600183614a43565b855490915060009061404690600190614a43565b90508082146140ab57600086600001828154811061406657614066614a56565b906000526020600020015490508087600001848154811061408957614089614a56565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806140bc576140bc614a6c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f2b565b6000915050610f2b565b5092915050565b600081815260018301602052604081205461414f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f2b565b506000610f2b565b60006020828403121561416957600080fd5b5035919050565b60008083601f84011261418257600080fd5b5081356001600160401b0381111561419957600080fd5b6020830191508360208260051b85010111156141b457600080fd5b9250929050565b6000806000604084860312156141d057600080fd5b8335925060208401356001600160401b038111156141ed57600080fd5b6141f986828701614170565b9497909650939450505050565b63ffffffff811681146110e557600080fd5b6000806040838503121561422b57600080fd5b82359150602083013561423d81614206565b809150509250929050565b60006020828403121561425a57600080fd5b81356001600160a01b038116811461379f57600080fd5b6020808252825182820181905260009190848201906040850190845b818110156134af5783516001600160a01b03168352928401929184019160010161428d565b602080825260049082015263444f4e4560e01b604082015260600190565b60208082526006908201526514105554d15160d21b604082015260600190565b6020808252601690820152752727aa2fa0a62627aba2a22faa27afaa2924a3a3a2a960511b604082015260600190565b80516001600160401b038116811461433757600080fd5b919050565b8051801515811461433757600080fd5b600080600080600060a0868803121561436457600080fd5b85516006811061437357600080fd5b945061438160208701614320565b9350604086015161ffff8116811461439857600080fd5b92506143a66060870161433c565b915060808601516143b681614206565b809150509295509295909350565b634e487b7160e01b600052602160045260246000fd5b6020808252600a908201526927a7262cafa0a226a4a760b11b604082015260600190565b601f8201601f191681016001600160401b038111828210171561443157634e487b7160e01b600052604160045260246000fd5b6040525050565b600060a0828403121561444a57600080fd5b60405160a081018181106001600160401b038211171561447a57634e487b7160e01b600052604160045260246000fd5b6040528251815260208301516004811061449357600080fd5b60208201526144a460408401614320565b60408201526144b560608401614320565b60608201526144c660808401614320565b60808201529392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f2b57610f2b6144d2565b6020808252600c908201526b15d0525517d512535153d55560a21b604082015260600190565b60208082526010908201526f2727afa9aaa1a42fa827a9a4aa24a7a760811b604082015260600190565b8381526060810160028410614562576145626143c4565b602082019390935260400152919050565b60006080828403121561458557600080fd5b604051608081018181106001600160401b03821117156145b557634e487b7160e01b600052604160045260246000fd5b6040526145c183614320565b81526145cf60208401614320565b60208201526145e060408401614320565b60408201526145f160608401614320565b60608201529392505050565b8481526080810160048510614614576146146143c4565b60208201949094526001600160401b0392831660408201529116606090910152919050565b600381106110e5576110e56143c4565b8381526060810161456284614639565b60006020828403121561466b57600080fd5b61379f8261433c565b8082028115828204841417610f2b57610f2b6144d2565b6000826146a857634e487b7160e01b600052601260045260246000fd5b500490565b6001600160401b038181168382160280821691908281146146d0576146d06144d2565b505092915050565b6001600160401b03828116828216039080821115614101576141016144d2565b6001600160401b03818116838216019080821115614101576141016144d2565b8481526080810161461485614639565b600060033d11156147415760046000803e5060005160e01c5b90565b600060443d10156147525790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561478157505050505090565b82850191508151818111156147995750505050505090565b843d87010160208285010111156147b35750505050505090565b6147c2602082860101876143fe565b509095945050505050565b6147d686614639565b858152600060206001600160401b03808816602085015280871660408501525060a0606084015284518060a085015260005b818110156148245786810183015185820160c001528201614808565b50600060c0828601015260c0601f19601f830116850101925050508260808301529695505050505050565b805160208201516001600160e01b0319808216929190600483101561487e5780818460040360031b1b83161693505b505050919050565b61488f85614639565b9384526001600160401b0392831660208501529116604083015260a0606083018190526009908301526821a0a82fa2a92927a960b91b60c0830152608082015260e00190565b606081016148e285614639565b9381526001600160401b039283166020820152911660409091015290565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000604082018583526020604060208501528185835260608501905060608660051b86010192508660005b878110156149c357868503605f190183528135368a9003601e1901811261497a57600080fd5b890184810190356001600160401b0381111561499557600080fd5b8036038213156149a457600080fd5b6149af878284614900565b965050509183019190830190600101614954565b509298975050505050505050565b6000606082840312156149e357600080fd5b604051606081018181106001600160401b0382111715614a1357634e487b7160e01b600052604160045260246000fd5b60405282518152614a2660208401614320565b6020820152614a3760408401614320565b60408201529392505050565b81810381811115610f2b57610f2b6144d2565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212205ea30faf884e26d1e90ed9111c8ccbd84fa172559deb1ea27cff51bc6487b13c64736f6c63430008180033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa868

-----Decoded View---------------
Arg [0] : _tradingFloor (address): 0x37792EecFA985D0b00a51864c970e7df406AA868

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000037792eecfa985d0b00a51864c970e7df406aa868


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.