Contract Diff Checker

Contract Name:
OrderBookV1

Contract Source Code:

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./AcceptableImplementationClaimableAdminStorage.sol";

/**
 * @title SafeUpgradeableClaimableAdmin
 * @dev based on Compound's Unitroller
 * https://github.com/compound-finance/compound-protocol/blob/a3214f67b73310d547e00fc578e8355911c9d376/contracts/Unitroller.sol
 */
contract AcceptableImplementationClaimableAdmin is
  AcceptableImplementationClaimableAdminStorage
{
  /**
   * @notice Emitted when pendingImplementation is changed
   */
  event NewPendingImplementation(
    address oldPendingImplementation,
    address newPendingImplementation
  );

  /**
   * @notice Emitted when pendingImplementation is accepted, which means delegation implementation is updated
   */
  event NewImplementation(address oldImplementation, address newImplementation);

  /**
   * @notice Emitted when pendingAdmin is changed
   */
  event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);

  /**
   * @notice Emitted when pendingAdmin is accepted, which means admin is updated
   */
  event NewAdmin(address oldAdmin, address newAdmin);

  /*** Admin Functions ***/
  function _setPendingImplementation(address newPendingImplementation) public {
    require(msg.sender == admin, "not admin");
    require(
      approvePendingImplementationInternal(newPendingImplementation),
      "INVALID_IMPLEMENTATION"
    );

    address oldPendingImplementation = pendingImplementation;

    pendingImplementation = newPendingImplementation;

    emit NewPendingImplementation(
      oldPendingImplementation,
      pendingImplementation
    );
  }

  /**
   * @notice Accepts new implementation. msg.sender must be pendingImplementation
   * @dev Admin function for new implementation to accept it's role as implementation
   */
  function _acceptImplementation() public returns (uint) {
    // Check caller is pendingImplementation and pendingImplementation ≠ address(0)
    require(
      msg.sender == pendingImplementation &&
        pendingImplementation != address(0),
      "Not the EXISTING pending implementation"
    );

    // Save current values for inclusion in log
    address oldImplementation = implementation;
    address oldPendingImplementation = pendingImplementation;

    implementation = pendingImplementation;

    pendingImplementation = address(0);

    emit NewImplementation(oldImplementation, implementation);
    emit NewPendingImplementation(
      oldPendingImplementation,
      pendingImplementation
    );

    return 0;
  }

  /**
   * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
   * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
   * @param newPendingAdmin New pending admin.
   */
  function _setPendingAdmin(address newPendingAdmin) public {
    // Check caller = admin
    require(msg.sender == admin, "Not Admin");

    // Save current value, if any, for inclusion in log
    address oldPendingAdmin = pendingAdmin;

    // Store pendingAdmin with value newPendingAdmin
    pendingAdmin = newPendingAdmin;

    // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
    emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
  }

  /**
   * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
   * @dev Admin function for pending admin to accept role and update admin
   */
  function _acceptAdmin() public {
    // Check caller is pendingAdmin and pendingAdmin ≠ address(0)
    require(
      msg.sender == pendingAdmin && pendingAdmin != address(0),
      "Not the EXISTING pending admin"
    );

    // Save current values for inclusion in log
    address oldAdmin = admin;
    address oldPendingAdmin = pendingAdmin;

    // Store admin with value pendingAdmin
    admin = pendingAdmin;

    // Clear the pending value
    pendingAdmin = address(0);

    emit NewAdmin(oldAdmin, admin);
    emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
  }

  constructor(address _initialAdmin) {
    admin = _initialAdmin;
    emit NewAdmin(address(0), _initialAdmin);
  }

  /**
   * @dev Delegates execution to an implementation contract.
   * It returns to the external caller whatever the implementation returns
   * or forwards reverts.
   */
  fallback() external payable {
    // delegate all other functions to current implementation
    (bool success, ) = implementation.delegatecall(msg.data);

    assembly {
      let free_mem_ptr := mload(0x40)
      returndatacopy(free_mem_ptr, 0, returndatasize())

      switch success
      case 0 {
        revert(free_mem_ptr, returndatasize())
      }
      default {
        return(free_mem_ptr, returndatasize())
      }
    }
  }

  receive() external payable {}

  function approvePendingImplementationInternal(
    address // _implementation
  ) internal virtual returns (bool) {
    return true;
  }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

contract ClaimableAdminStorage {
  /**
   * @notice Administrator for this contract
   */
  address public admin;

  /**
   * @notice Pending administrator for this contract
   */
  address public pendingAdmin;

  /*** Modifiers ***/

  modifier onlyAdmin() {
    require(msg.sender == admin, "ONLY_ADMIN");
    _;
  }

  /*** Constructor ***/

  constructor() {
    // Set admin to caller
    admin = msg.sender;
  }
}

contract AcceptableImplementationClaimableAdminStorage is
  ClaimableAdminStorage
{
  /**
   * @notice Active logic
   */
  address public implementation;

  /**
   * @notice Pending logic
   */
  address public pendingImplementation;
}

contract AcceptableRegistryImplementationClaimableAdminStorage is
  AcceptableImplementationClaimableAdminStorage
{
  /**
   * @notice System Registry
   */
  address public registry;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./AcceptableImplementationClaimableAdmin.sol";
import "./IContractRegistryBase.sol";

/**
 * @title AcceptableRegistryImplementationClaimableAdmin
 */
contract AcceptableRegistryImplementationClaimableAdmin is
  AcceptableImplementationClaimableAdmin,
  AcceptableRegistryImplementationClaimableAdminStorage
{
  bytes32 public immutable CONTRACT_NAME_HASH;

  constructor(
    address _registry,
    string memory proxyName,
    address _initialAdmin
  ) AcceptableImplementationClaimableAdmin(_initialAdmin) {
    registry = _registry;
    CONTRACT_NAME_HASH = keccak256(abi.encodePacked(proxyName));
  }

  function approvePendingImplementationInternal(
    address _implementation
  ) internal view override returns (bool) {
    return
      IContractRegistryBase(registry).isImplementationValidForProxy(
        CONTRACT_NAME_HASH,
        _implementation
      );
  }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

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

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

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

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

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

  uint256 public constant ACCURACY_IMPROVEMENT_SCALE = 1e9;

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface IFundingRateModel {
  // return value is the "funding paid by heavier side" in PRECISION per OI (heavier side) per second
  // e.g : (0.01 * PRECISION) = Paying (heavier) side (as a whole) pays 1% of funding per second for each OI unit
  function getFundingRate(
    uint256 pairId,
    uint256 openInterestLong,
    uint256 openInterestShort,
    uint256 pairMaxOpenInterest
  ) external view returns (uint256);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface IInterestRateModel {
  // Returns asset/second of interest per borrowed unit
  // e.g : (0.01 * PRECISION) = 1% of interest per second
  function getBorrowRate(uint256 utilization) external view returns (uint256);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./LexErrors.sol";
import "./LexPoolAdminEnums.sol";
import "./IPoolAccountantV1.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface LexPoolStructs {
  struct PendingDeposit {
    uint256 amount;
    uint256 minAmountOut;
  }

  struct PendingRedeem {
    uint256 amount;
    uint256 minAmountOut;
    uint256 maxAmountOut;
  }
}

interface LexPoolEvents is LexPoolAdminEnums {
  event NewEpoch(
    uint256 epochId,
    int256 reportedUnrealizedPricePnL,
    uint256 exchangeRate,
    uint256 virtualUnderlyingBalance,
    uint256 totalSupply
  );

  event AddressUpdated(LexPoolAddressesEnum indexed enumCode, address a);
  event NumberUpdated(LexPoolNumbersEnum indexed enumCode, uint value);
  event DepositRequest(
    address indexed user,
    uint256 amount,
    uint256 minAmountOut,
    uint256 processingEpoch
  );
  event RedeemRequest(
    address indexed user,
    uint256 amount,
    uint256 minAmountOut,
    uint256 processingEpoch
  );
  event ProcessedDeposit(
    address indexed user,
    bool deposited,
    uint256 depositedAmount
  );
  event ProcessedRedeem(
    address indexed user,
    bool redeemed,
    uint256 withdrawnAmount // Underlying amount
  );
  event CanceledDeposit(
    address indexed user,
    uint256 epoch,
    uint256 cancelledAmount
  );
  event CanceledRedeem(
    address indexed user,
    uint256 epoch,
    uint256 cancelledAmount
  );
  event ImmediateDepositAllowedToggled(bool indexed value);
  event ImmediateDeposit(
    address indexed depositor,
    uint256 depositAmount,
    uint256 mintAmount
  );
  event ReservesWithdrawn(
    address _to,
    uint256 interestShare,
    uint256 totalFundingShare
  );
}

interface ILexPoolFunctionality is
  IERC20,
  LexPoolStructs,
  LexPoolEvents,
  LexErrors
{
  function setPoolAccountant(
    IPoolAccountantFunctionality _poolAccountant
  ) external;

  function setPnlRole(address pnl) external;

  function setMaxExtraWithdrawalAmountF(uint256 maxExtra) external;

  function setEpochsDelayDeposit(uint256 delay) external;

  function setEpochsDelayRedeem(uint256 delay) external;

  function setEpochDuration(uint256 duration) external;

  function setMinDepositAmount(uint256 amount) external;

  function toggleImmediateDepositAllowed() external;

  function reduceReserves(
    address _to
  ) external returns (uint256 interestShare, uint256 totalFundingShare);

  function requestDeposit(
    uint256 amount,
    uint256 minAmountOut,
    bytes32 domain,
    bytes32 referralCode
  ) external;

  function requestDepositViaIntent(
    address user,
    uint256 amount,
    uint256 minAmountOut,
    bytes32 domain,
    bytes32 referralCode
  ) external;

  function requestRedeem(uint256 amount, uint256 minAmountOut) external;

  function requestRedeemViaIntent(
    address user,
    uint256 amount,
    uint256 minAmountOut
  ) external;

  function processDeposit(
    address[] memory users
  )
    external
    returns (
      uint256 amountDeposited,
      uint256 amountCancelled,
      uint256 counterDeposited,
      uint256 counterCancelled
    );

  function cancelDeposits(
    address[] memory users,
    uint256[] memory epochs
  ) external;

  function processRedeems(
    address[] memory users
  )
    external
    returns (
      uint256 amountRedeemed,
      uint256 amountCancelled,
      uint256 counterDeposited,
      uint256 counterCancelled
    );

  function cancelRedeems(
    address[] memory users,
    uint256[] memory epochs
  ) external;

  function nextEpoch(
    int256 totalUnrealizedPricePnL
  ) external returns (uint256 newExchangeRate);

  function currentVirtualUtilization() external view returns (uint256);

  function currentVirtualUtilization(
    uint256 totalBorrows,
    uint256 totalReserves,
    int256 unrealizedFunding
  ) external view returns (uint256);

  function virtualBalanceForUtilization() external view returns (uint256);

  function virtualBalanceForUtilization(
    uint256 extraAmount,
    int256 unrealizedFunding
  ) external view returns (uint256);

  function underlyingBalanceForExchangeRate() external view returns (uint256);

  function sendAssetToTrader(address to, uint256 amount) external;

  function isUtilizationForLPsValid() external view returns (bool);
}

interface ILexPoolV1 is ILexPoolFunctionality {
  function name() external view returns (string memory);

  function symbol() external view returns (string memory);

  function SELF_UNIT_SCALE() external view returns (uint);

  function underlyingDecimals() external view returns (uint256);

  function poolAccountant() external view returns (address);

  function underlying() external view returns (IERC20);

  function tradingFloor() external view returns (address);

  function currentEpoch() external view returns (uint256);

  function currentExchangeRate() external view returns (uint256);

  function nextEpochStartMin() external view returns (uint256);

  function epochDuration() external view returns (uint256);

  function minDepositAmount() external view returns (uint256);

  function epochsDelayDeposit() external view returns (uint256);

  function epochsDelayRedeem() external view returns (uint256);

  function immediateDepositAllowed() external view returns (bool);

  function pendingDeposits(
    uint epoch,
    address account
  ) external view returns (PendingDeposit memory);

  function pendingRedeems(
    uint epoch,
    address account
  ) external view returns (PendingRedeem memory);

  function pendingDepositAmount() external view returns (uint256);

  function pendingWithdrawalAmount() external view returns (uint256);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

// import "./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);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./LexErrors.sol";
import "./ILexPoolV1.sol";
import "./IInterestRateModel.sol";
import "./IFundingRateModel.sol";
import "./TradingEnumsV1.sol";

interface PoolAccountantStructs {
  // @note To be used for passing information in function calls
  struct PositionRegistrationParams {
    uint256 collateral;
    uint32 leverage;
    bool long;
    uint64 openPrice;
    uint64 tp;
  }

  struct PairFunding {
    // Slot 0
    int256 accPerOiLong; // 32 bytes -- Underlying Decimals
    // Slot 1
    int256 accPerOiShort; // 32 bytes -- Underlying Decimals
    // Slot 2
    uint256 lastUpdateTimestamp; // 32 bytes
  }

  struct TradeInitialAccFees {
    // Slot 0
    uint256 borrowIndex; // 32 bytes
    // Slot 1
    int256 funding; // 32 bytes -- underlying units -- Underlying Decimals
  }

  struct PairOpenInterest {
    // Slot 0
    uint256 long; // 32 bytes -- underlying units -- Dynamic open interest for long positions
    // Slot 1
    uint256 short; // 32 bytes -- underlying units -- Dynamic open interest for short positions
  }

  // This struct is not kept in storage
  struct PairFromTo {
    string from;
    string to;
  }

  struct Pair {
    // Slot 0
    uint16 id; // 02 bytes
    uint16 groupId; // 02 bytes
    uint16 feeId; // 02 bytes
    uint32 minLeverage; // 04 bytes
    uint32 maxLeverage; // 04 bytes
    uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
    // Slot 1
    uint256 maxPositionSize; // 32 bytes -- underlying units
    // Slot 2
    uint256 maxGain; // 32 bytes -- underlying units
    // Slot 3
    uint256 maxOpenInterest; // 32 bytes -- Underlying units
    // Slot 4
    uint256 maxSkew; // 32 bytes -- underlying units
    // Slot 5
    uint256 minOpenFee; // 32 bytes -- underlying units. MAX_UINT means use the default group level value
    // Slot 6
    uint256 minPerformanceFee; // 32 bytes -- underlying units
  }

  struct Group {
    // Slot 0
    uint16 id; // 02 bytes
    uint32 minLeverage; // 04 bytes
    uint32 maxLeverage; // 04 bytes
    uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
    // Slot 1
    uint256 maxPositionSize; // 32 bytes (Underlying units)
    // Slot 2
    uint256 minOpenFee; // 32 bytes (Underlying uints). MAX_UINT means use the default global level value
  }

  struct Fee {
    // Slot 0
    uint16 id; // 02 bytes
    uint32 openFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
    uint32 closeFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
    uint32 performanceFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of performance)
  }
}

interface PoolAccountantEvents is PoolAccountantStructs {
  event PairAdded(
    uint256 indexed id,
    string indexed from,
    string indexed to,
    Pair pair
  );
  event PairUpdated(uint256 indexed id, Pair pair);

  event GroupAdded(uint256 indexed id, string indexed groupName, Group group);
  event GroupUpdated(uint256 indexed id, Group group);

  event FeeAdded(uint256 indexed id, string indexed name, Fee fee);
  event FeeUpdated(uint256 indexed id, Fee fee);

  event TradeInitialAccFeesStored(
    bytes32 indexed positionId,
    uint256 borrowIndex,
    // uint256 rollover,
    int256 funding
  );

  event AccrueFunding(
    uint256 indexed pairId,
    int256 valueLong,
    int256 valueShort
  );

  event ProtocolFundingShareAccrued(
    uint16 indexed pairId,
    uint256 protocolFundingShare
  );
  // event AccRolloverFeesStored(uint256 pairIndex, uint256 value);

  event FeesCharged(
    bytes32 indexed positionId,
    address indexed trader,
    uint16 indexed pairId,
    PositionRegistrationParams positionRegistrationParams,
    //        bool long,
    //        uint256 collateral, // Underlying Decimals
    //        uint256 leverage,
    int256 profitPrecision, // PRECISION
    uint256 interest,
    int256 funding, // Underlying Decimals
    uint256 closingFee,
    uint256 tradeValue
  );

  event PerformanceFeeCharging(
    bytes32 indexed positionId,
    uint256 performanceFee
  );

  event MaxOpenInterestUpdated(uint256 pairIndex, uint256 maxOpenInterest);

  event AccrueInterest(
    uint256 cash,
    uint256 totalInterestNew,
    uint256 borrowIndexNew,
    uint256 interestShareNew
  );

  event Borrow(
    uint256 indexed pairId,
    uint256 borrowAmount,
    uint256 newTotalBorrows
  );

  event Repay(
    uint256 indexed pairId,
    uint256 repayAmount,
    uint256 newTotalBorrows
  );
}

interface IPoolAccountantFunctionality is
  PoolAccountantStructs,
  PoolAccountantEvents,
  LexErrors,
  TradingEnumsV1
{
  function setTradeIncentivizer(address _tradeIncentivizer) external;

  function setMaxGainF(uint256 _maxGainF) external;

  function setFrm(IFundingRateModel _frm) external;

  function setMinOpenFee(uint256 min) external;

  function setLexPartF(uint256 partF) external;

  function setFundingRateMax(uint256 maxValue) external;

  function setLiquidationThresholdF(uint256 threshold) external;

  function setLiquidationFeeF(uint256 fee) external;

  function setIrm(IInterestRateModel _irm) external;

  function setIrmHard(IInterestRateModel _irm) external;

  function setInterestShareFactor(uint256 factor) external;
  
  function setFundingShareFactor(uint256 factor) external;

  function setBorrowRateMax(uint256 rate) external;

  function setMaxTotalBorrows(uint256 maxBorrows) external;

  function setMaxVirtualUtilization(uint256 _maxVirtualUtilization) external;

  function resetTradersPairGains(uint256 pairId) external;

  function addGroup(Group calldata _group) external;

  function updateGroup(Group calldata _group) external;

  function addFee(Fee calldata _fee) external;

  function updateFee(Fee calldata _fee) external;

  function addPair(Pair calldata _pair) external;

  function addPairs(Pair[] calldata _pairs) external;

  function updatePair(Pair calldata _pair) external;

  function readAndZeroReserves()
    external
    returns (uint256 accumulatedInterestShare,
             uint256 accFundingShare);

  function registerOpenTrade(
    bytes32 positionId,
    address trader,
    uint16 pairId,
    uint256 collateral,
    uint32 leverage,
    bool long,
    uint256 tp,
    uint256 openPrice
  ) external returns (uint256 fee, uint256 lexPartFee);

  function registerCloseTrade(
    bytes32 positionId,
    address trader,
    uint16 pairId,
    PositionRegistrationParams calldata positionRegistrationParams,
    uint256 closePrice,
    PositionCloseType positionCloseType
  )
    external
    returns (
      uint256 closingFee,
      uint256 tradeValue,
      int256 profitPrecision,
      uint finalClosePrice
    );

  function registerUpdateTp(
    bytes32 positionId,
    address trader,
    uint16 pairId,
    uint256 collateral,
    uint32 leverage,
    bool long,
    uint256 openPrice,
    uint256 oldTriggerPrice,
    uint256 triggerPrice
  ) external;

  // function registerUpdateSl(
  //     address trader,
  //     uint256 pairIndex,
  //     uint256 index,
  //     uint256 collateral,
  //     uint256 leverage,
  //     bool long,
  //     uint256 openPrice,
  //     uint256 triggerPrice
  // ) external returns (uint256 fee);

  function accrueInterest()
    external
    returns (
      uint256 totalInterestNew,
      uint256 interestShareNew,
      uint256 borrowIndexNew
    );

  // Limited only for the LexPool
  function accrueInterest(
    uint256 availableCash
  )
    external
    returns (
      uint256 totalInterestNew,
      uint256 interestShareNew,
      uint256 borrowIndexNew
    );

  function getTradeClosingValues(
    bytes32 positionId,
    uint16 pairId,
    PositionRegistrationParams calldata positionRegistrationParams,
    uint256 closePrice,
    bool isLiquidation
  )
    external
    returns (
      uint256 tradeValue, // Underlying Decimals
      uint256 safeClosingFee,
      int256 profitPrecision,
      uint256 interest,
      int256 funding
    );

  function getTradeLiquidationPrice(
    bytes32 positionId,
    uint16 pairId,
    uint256 openPrice, // PRICE_SCALE (8)
    uint256 tp,
    bool long,
    uint256 collateral, // Underlying Decimals
    uint32 leverage
  )
    external
    returns (
      uint256 // PRICE_SCALE (8)
    );

  function calcTradeDynamicFees(
    bytes32 positionId,
    uint16 pairId,
    bool long,
    uint256 collateral,
    uint32 leverage,
    uint256 openPrice,
    uint256 tp
  ) external returns (uint256 interest, int256 funding);

  function unrealizedFunding() external view returns (int256);

  function totalBorrows() external view returns (uint256);

  function interestShare() external view returns (uint256);
  
  function fundingShare() external view returns (uint256);

  function totalReservesView() external view returns (uint256);

  function borrowsAndInterestShare()
    external
    view
    returns (uint256 totalBorrows, uint256 totalInterestShare);

  function pairTotalOpenInterest(
    uint256 pairIndex
  ) external view returns (int256);

  function pricePnL(
    uint256 pairId,
    uint256 price
  ) external view returns (int256);

  function getAllSupportedPairIds() external view returns (uint16[] memory);

  function getAllSupportedGroupsIds() external view returns (uint16[] memory);

  function getAllSupportedFeeIds() external view returns (uint16[] memory);
}

interface IPoolAccountantV1 is IPoolAccountantFunctionality {
  function totalBorrows() external view returns (uint256);

  function maxTotalBorrows() external view returns (uint256);

  function pairBorrows(uint256 pairId) external view returns (uint256);

  function groupBorrows(uint256 groupId) external view returns (uint256);

  function pairMaxBorrow(uint16 pairId) external view returns (uint256);

  function groupMaxBorrow(uint16 groupId) external view returns (uint256);

  function lexPool() external view returns (ILexPoolV1);

  function maxGainF() external view returns (uint256);

  function interestShareFactor() external view returns (uint256);
  
  function fundingShareFactor() external view returns (uint256);

  function frm() external view returns (IFundingRateModel);

  function irm() external view returns (IInterestRateModel);

  function pairs(uint16 pairId) external view returns (Pair memory);

  function groups(uint16 groupId) external view returns (Group memory);

  function fees(uint16 feeId) external view returns (Fee memory);

  function openInterestInPair(
    uint pairId
  ) external view returns (PairOpenInterest memory);

  function minOpenFee() external view returns (uint256);

  function liquidationThresholdF() external view returns (uint256);

  function liquidationFeeF() external view returns (uint256);

  function lexPartF() external view returns (uint256);

  function tradersPairGains(uint256 pairId) external view returns (int256);

  function calcBorrowAmount(
    uint256 collateral,
    uint256 leverage,
    bool long,
    uint256 openPrice,
    uint256 tp
  ) external pure returns (uint256);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../../AdministrationContracts/IContractRegistryBase.sol";
import "./IGlobalLock.sol";

interface IRegistryV1Functionality is IContractRegistryBase, IGlobalLock {
  // **** Locking mechanism ****

  function isTradersPortalAndLocker(
    address _address
  ) external view returns (bool);

  function isTriggersAndLocker(address _address) external view returns (bool);

  function isTradersPortalOrTriggersAndLocker(
    address _address
  ) external view returns (bool);
}

interface IRegistryV1 is IRegistryV1Functionality {
  // **** Public Storage params ****

  function feesManagers(address asset) external view returns (address);

  function orderBook() external view returns (address);

  function tradersPortal() external view returns (address);

  function triggers() external view returns (address);

  function tradeIntentsVerifier() external view returns (address);

  function liquidityIntentsVerifier() external view returns (address);

  function chipsIntentsVerifier() external view returns (address);

  function lexProxiesFactory() external view returns (address);

  function chipsFactory() external view returns (address);

  /**
   * @return An array of all supported trading floors
   */
  function getAllSupportedTradingFloors()
    external
    view
    returns (address[] memory);

  /**
   * @return An array of all supported settlement assets
   */
  function getSettlementAssetsForTradingFloor(
    address _tradingFloor
  ) external view returns (address[] memory);

  /**
   * @return The spender role address that is set for this chip
   */
  function getValidSpenderTargetForChipByRole(
    address chip,
    string calldata role
  ) external view returns (address);

  /**
   * @return the address of the valid 'burnHandler' for the chip
   */
  function validBurnHandlerForChip(
    address chip
  ) external view returns (address);

  /**
   * @return The address matching for the given role
   */
  function getDynamicRoleAddress(
    string calldata _role
  ) external view returns (address);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  // *** Views ***

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

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

  // *** Public Storage addresses ***

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

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

  function registry() external view returns (address);

  // *** Public Storage params ***

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

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

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

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

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

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

  function maxSlF() external view returns (uint);

  function maxTradesPerPair() external view returns (uint);

  function maxSanityProfitF() external view returns (uint);

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface LexErrors {
  enum CapType {
    NONE, // 0
    MIN_OPEN_FEE, // 1
    MAX_POS_SIZE_PAIR, // 2
    MAX_POS_SIZE_GROUP, // 3
    MAX_LEVERAGE, // 4
    MIN_LEVERAGE, // 5
    MAX_VIRTUAL_UTILIZATION, // 6
    MAX_OPEN_INTEREST, // 7
    MAX_ABS_SKEW, // 8
    MAX_BORROW_PAIR, // 9
    MAX_BORROW_GROUP, // 10
    MIN_DEPOSIT_AMOUNT, // 11
    MAX_ACCUMULATED_GAINS, // 12
    BORROW_RATE_MAX, // 13
    FUNDING_RATE_MAX, // 14
    MAX_POTENTIAL_GAIN, // 15
    MAX_TOTAL_BORROW, // 16
    MIN_PERFORMANCE_FEE // 17
    //...
  }
  error CapError(CapType, uint256 value);
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

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

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

// 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
  }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

interface TradingEnumsV1 {
  enum PositionPhase {
    NONE,
    OPEN_MARKET,
    OPEN_LIMIT,
    OPENED,
    CLOSE_MARKET,
    CLOSED
  }

  enum OpenOrderType {
    NONE,
    MARKET,
    LIMIT
  }
  enum CloseOrderType {
    NONE,
    MARKET
  }
  enum FeeType {
    NONE,
    OPEN_FEE,
    CLOSE_FEE,
    TRIGGER_FEE
  }
  enum LimitTrigger {
    NONE,
    TP,
    SL,
    LIQ
  }
  enum PositionField {
    NONE,
    TP,
    SL
  }

  enum PositionCloseType {
    NONE,
    TP,
    SL,
    LIQ,
    MARKET
  }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "./TradingEnumsV1.sol";

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

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

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

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

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

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

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

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../../AdministrationContracts/AcceptableRegistryImplementationClaimableAdmin.sol";

/**
 * @title OrderBookProxy
 * @dev Used as the upgradable order book of the Lynx platform
 */
contract OrderBookProxy is AcceptableRegistryImplementationClaimableAdmin {
  constructor(
    address _registry
  )
    AcceptableRegistryImplementationClaimableAdmin(
      _registry,
      "OrderBook",
      msg.sender
    )
  {}
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../../AdministrationContracts/AcceptableImplementationClaimableAdmin.sol";
import "../interfaces/OrderBookStructsV1.sol";
import "../Common/CommonScales.sol";

/**
 * @title OrderBookStorageV1
 * @dev Storage contract for the OrderBook
 */
contract OrderBookStorageV1 is
  AcceptableRegistryImplementationClaimableAdminStorage,
  OrderBookStructsV1,
  CommonScales
{
  // ***** Roles *****

  address public tradingFloor;

  // ***** Orders *****

  // order id => position (index + 1) in the 'allPendingUpdateOrderIds' array
  mapping(bytes32 => uint) public updateOrderIdPositionInList;

  bytes32[] public allPendingUpdateOrderIds;

  // Position Id => UpdatePositionFieldOrder
  mapping(bytes32 => UpdatePositionFieldOrder)
    public pendingUpdateTradeFieldOrdersById;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import "../interfaces/IOrderBookV1.sol";
import "../interfaces/IRegistryV1.sol";
import "../interfaces/ITradingFloorV1.sol";
import "./OrderBookStorage.sol";
import "./OrderBookProxy.sol";

/**
 * @title OrderBookV1
 * @dev OrderBook contract for the Lynx platform, allows for more versatile order storing and management
 */
contract OrderBookV1 is OrderBookStorageV1, IOrderBookFunctionalityV1 {
  // ***** Events *****

  event TradingFloorSet(address indexed tradingFloor);

  event NumberUpdated(string indexed name, uint value);

  event UpdateLivePositionOrderSet(
    bytes32 indexed positionId,
    UpdatePositionFieldOrder order
  );

  event UpdateLivePositionOrderRemoved(bytes32 indexed positionId);

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

  modifier onlyTradingFloor() {
    require(msg.sender == tradingFloor, "!TradingFloor");
    _;
  }

  modifier onlyTradersPortalFloor() {
    require(
      msg.sender == IRegistryV1(registry).tradersPortal(),
      "!TradersPortal"
    );
    _;
  }

  modifier onlyTradersPortalFloorOrTriggers() {
    require(
      msg.sender == IRegistryV1(registry).tradersPortal() ||
        msg.sender == IRegistryV1(registry).triggers(),
      "!(TradersPortal||Triggers)"
    );
    _;
  }

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

  function getAllPendingUpdateOrderIds()
    external
    view
    returns (bytes32[] memory)
  {
    return allPendingUpdateOrderIds;
  }

  // ***** Initialization functions *****

  function _become(OrderBookProxy orderBookProxy) public {
    require(
      msg.sender == orderBookProxy.admin(),
      "only OrderBookProxy admin can change brains"
    );
    require(
      orderBookProxy._acceptImplementation() == 0,
      "change not authorized"
    );
  }

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

  function setTradingFloor(address _tradingFloor) external onlyAdmin {
    require(tradingFloor == address(0), "ALREADY_INITIALIZED");
    require(_tradingFloor != address(0), "CANNOT_BE_ZERO_ADDRESS");
    registry = ITradingFloorV1(_tradingFloor).registry();
    tradingFloor = _tradingFloor;
    emit TradingFloorSet(tradingFloor);
  }

  // ***** Position Update orders *****

  /**
   * @dev Store a new Single-Field update order for a position.
   * @param _positionId The position id.
   * @param orderType The type of the order.
   * @param fieldValue The value of the order.
   * @return The order.
   */
  function storeUpdatePositionSingleFieldOrder(
    bytes32 _positionId,
    UpdatePositionFieldOrderType orderType,
    uint64 fieldValue
  )
    external
    override
    onlyTradersPortalFloor
    returns (UpdatePositionFieldOrder memory)
  {
    require(
      orderType == UpdatePositionFieldOrderType.UPDATE_TP ||
        orderType == UpdatePositionFieldOrderType.UPDATE_SL,
      "NOT_SUPPORTED"
    );
    require(
      pendingUpdateTradeFieldOrdersById[_positionId].timestamp == 0,
      "UPDATE_ORDER_EXISTS_FOR_TRADE"
    );

    addUpdateOrderIdToGeneralList(_positionId);

    UpdatePositionFieldOrder
      memory updateTradeFieldOrder = UpdatePositionFieldOrder({
        positionId: _positionId,
        orderType: orderType,
        timestamp: uint64(block.timestamp),
        fieldValueA: fieldValue,
        fieldValueB: 0
      });

    pendingUpdateTradeFieldOrdersById[_positionId] = updateTradeFieldOrder;

    emit UpdateLivePositionOrderSet(_positionId, updateTradeFieldOrder);

    return updateTradeFieldOrder;
  }

  /**
   * @dev Store a new Double-Field update order for a position.
   * @param _positionId The position id.
   * @param orderType The type of the order.
   * @param fieldValueA The value of the order.
   * @param fieldValueB The value of the order.
   * @return The order.
   */
  function storeUpdatePositionDoubleFieldOrder(
    bytes32 _positionId,
    UpdatePositionFieldOrderType orderType,
    uint64 fieldValueA,
    uint64 fieldValueB
  )
    external
    override
    onlyTradersPortalFloor
    returns (UpdatePositionFieldOrder memory)
  {
    require(
      orderType == UpdatePositionFieldOrderType.UPDATE_TP_AND_SL,
      "NOT_SUPPORTED"
    );
    require(
      pendingUpdateTradeFieldOrdersById[_positionId].timestamp == 0,
      "UPDATE_ORDER_EXISTS_FOR_TRADE"
    );

    addUpdateOrderIdToGeneralList(_positionId);

    UpdatePositionFieldOrder
      memory updateTradeFieldOrder = UpdatePositionFieldOrder({
        positionId: _positionId,
        orderType: orderType,
        timestamp: uint64(block.timestamp),
        fieldValueA: fieldValueA,
        fieldValueB: fieldValueB
      });

    pendingUpdateTradeFieldOrdersById[_positionId] = updateTradeFieldOrder;

    emit UpdateLivePositionOrderSet(_positionId, updateTradeFieldOrder);

    return updateTradeFieldOrder;
  }

  /**
   * @dev Read and delete a pending update order for a position.
   * @notice Will revert if no update order for position exists
   * @param _positionId The position id.
   * @return order The deleted order.
   */
  function readAndDeleteUpdatePositionOrder(
    bytes32 _positionId
  )
    external
    override
    onlyTradersPortalFloorOrTriggers
    returns (UpdatePositionFieldOrder memory order)
  {
    order = pendingUpdateTradeFieldOrdersById[_positionId];
    require(order.timestamp > 0, "NO_SUCH_UPDATE_ORDER");
    delete pendingUpdateTradeFieldOrdersById[_positionId];

    removeUpdateOrderIdFromGeneralList(_positionId);
  }

  // ***** Internal General-Lists functions *****

  /**
   * @dev Add an order id to the general list of pending update orders.
   * @param _orderId The order id.
   */
  function addUpdateOrderIdToGeneralList(bytes32 _orderId) internal {
    uint indexInList = allPendingUpdateOrderIds.length;
    allPendingUpdateOrderIds.push(_orderId);
    updateOrderIdPositionInList[_orderId] = indexInList + 1;
  }

  /**
   * @dev Remove an order id from the general list of pending update orders.
   * @param _orderId The order id.
   */
  function removeUpdateOrderIdFromGeneralList(bytes32 _orderId) internal {
    uint positionInList = updateOrderIdPositionInList[_orderId];

    if (allPendingUpdateOrderIds.length > 1) {
      bytes32 lastOrderIdInList = allPendingUpdateOrderIds[
        allPendingUpdateOrderIds.length - 1
      ];
      if (lastOrderIdInList != _orderId) {
        allPendingUpdateOrderIds[positionInList - 1] = lastOrderIdInList;
        updateOrderIdPositionInList[lastOrderIdInList] = positionInList;
      }
    }

    allPendingUpdateOrderIds.pop();

    // Delete the position of the order id
    updateOrderIdPositionInList[_orderId] = 0;

    emit UpdateLivePositionOrderRemoved(_orderId);
  }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):