/

    Contract Diff Checker

    Contract Name:
    RegistryV1

    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;
    
    interface IContractRegistryBase {
      function isImplementationValidForProxy(
        bytes32 proxyNameHash,
        address _implementation
      ) external view returns (bool);
    }

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.24;
    
    contract ChipEnumsV1 {
      enum ChipMode {
        NONE,
        LOCAL,
        REMOTE,
        HYBRID
      }
    }

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

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    interface IGlobalLock {
      function lock() external;
      function freeLock() external;
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    interface IInterestRateModel {
      // Returns asset/second of interest per borrowed unit
      // e.g : (0.01 * PRECISION) = 1% of interest per second
      function getBorrowRate(uint256 utilization) external view returns (uint256);
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "./LexErrors.sol";
    import "./LexPoolAdminEnums.sol";
    import "./IPoolAccountantV1.sol";
    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
    
    interface LexPoolStructs {
      struct PendingDeposit {
        uint256 amount;
        uint256 minAmountOut;
      }
    
      struct PendingRedeem {
        uint256 amount;
        uint256 minAmountOut;
        uint256 maxAmountOut;
      }
    }
    
    interface LexPoolEvents is LexPoolAdminEnums {
      event NewEpoch(
        uint256 epochId,
        int256 reportedUnrealizedPricePnL,
        uint256 exchangeRate,
        uint256 virtualUnderlyingBalance,
        uint256 totalSupply
      );
    
      event AddressUpdated(LexPoolAddressesEnum indexed enumCode, address a);
      event NumberUpdated(LexPoolNumbersEnum indexed enumCode, uint value);
      event DepositRequest(
        address indexed user,
        uint256 amount,
        uint256 minAmountOut,
        uint256 processingEpoch
      );
      event RedeemRequest(
        address indexed user,
        uint256 amount,
        uint256 minAmountOut,
        uint256 processingEpoch
      );
      event ProcessedDeposit(
        address indexed user,
        bool deposited,
        uint256 depositedAmount
      );
      event ProcessedRedeem(
        address indexed user,
        bool redeemed,
        uint256 withdrawnAmount // Underlying amount
      );
      event CanceledDeposit(
        address indexed user,
        uint256 epoch,
        uint256 cancelledAmount
      );
      event CanceledRedeem(
        address indexed user,
        uint256 epoch,
        uint256 cancelledAmount
      );
      event ImmediateDepositAllowedToggled(bool indexed value);
      event ImmediateDeposit(
        address indexed depositor,
        uint256 depositAmount,
        uint256 mintAmount
      );
      event ReservesWithdrawn(
        address _to,
        uint256 interestShare,
        uint256 totalFundingShare
      );
    }
    
    interface ILexPoolFunctionality is
      IERC20,
      LexPoolStructs,
      LexPoolEvents,
      LexErrors
    {
      function setPoolAccountant(
        IPoolAccountantFunctionality _poolAccountant
      ) external;
    
      function setPnlRole(address pnl) external;
    
      function setMaxExtraWithdrawalAmountF(uint256 maxExtra) external;
    
      function setEpochsDelayDeposit(uint256 delay) external;
    
      function setEpochsDelayRedeem(uint256 delay) external;
    
      function setEpochDuration(uint256 duration) external;
    
      function setMinDepositAmount(uint256 amount) external;
    
      function toggleImmediateDepositAllowed() external;
    
      function reduceReserves(
        address _to
      ) external returns (uint256 interestShare, uint256 totalFundingShare);
    
      function requestDeposit(
        uint256 amount,
        uint256 minAmountOut,
        bytes32 domain,
        bytes32 referralCode
      ) external;
    
      function requestDepositViaIntent(
        address user,
        uint256 amount,
        uint256 minAmountOut,
        bytes32 domain,
        bytes32 referralCode
      ) external;
    
      function requestRedeem(uint256 amount, uint256 minAmountOut) external;
    
      function requestRedeemViaIntent(
        address user,
        uint256 amount,
        uint256 minAmountOut
      ) external;
    
      function processDeposit(
        address[] memory users
      )
        external
        returns (
          uint256 amountDeposited,
          uint256 amountCancelled,
          uint256 counterDeposited,
          uint256 counterCancelled
        );
    
      function cancelDeposits(
        address[] memory users,
        uint256[] memory epochs
      ) external;
    
      function processRedeems(
        address[] memory users
      )
        external
        returns (
          uint256 amountRedeemed,
          uint256 amountCancelled,
          uint256 counterDeposited,
          uint256 counterCancelled
        );
    
      function cancelRedeems(
        address[] memory users,
        uint256[] memory epochs
      ) external;
    
      function nextEpoch(
        int256 totalUnrealizedPricePnL
      ) external returns (uint256 newExchangeRate);
    
      function currentVirtualUtilization() external view returns (uint256);
    
      function currentVirtualUtilization(
        uint256 totalBorrows,
        uint256 totalReserves,
        int256 unrealizedFunding
      ) external view returns (uint256);
    
      function virtualBalanceForUtilization() external view returns (uint256);
    
      function virtualBalanceForUtilization(
        uint256 extraAmount,
        int256 unrealizedFunding
      ) external view returns (uint256);
    
      function underlyingBalanceForExchangeRate() external view returns (uint256);
    
      function sendAssetToTrader(address to, uint256 amount) external;
    
      function isUtilizationForLPsValid() external view returns (bool);
    }
    
    interface ILexPoolV1 is ILexPoolFunctionality {
      function name() external view returns (string memory);
    
      function symbol() external view returns (string memory);
    
      function SELF_UNIT_SCALE() external view returns (uint);
    
      function underlyingDecimals() external view returns (uint256);
    
      function poolAccountant() external view returns (address);
    
      function underlying() external view returns (IERC20);
    
      function tradingFloor() external view returns (address);
    
      function currentEpoch() external view returns (uint256);
    
      function currentExchangeRate() external view returns (uint256);
    
      function nextEpochStartMin() external view returns (uint256);
    
      function epochDuration() external view returns (uint256);
    
      function minDepositAmount() external view returns (uint256);
    
      function epochsDelayDeposit() external view returns (uint256);
    
      function epochsDelayRedeem() external view returns (uint256);
    
      function immediateDepositAllowed() external view returns (bool);
    
      function pendingDeposits(
        uint epoch,
        address account
      ) external view returns (PendingDeposit memory);
    
      function pendingRedeems(
        uint epoch,
        address account
      ) external view returns (PendingRedeem memory);
    
      function pendingDepositAmount() external view returns (uint256);
    
      function pendingWithdrawalAmount() external view returns (uint256);
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "./LexErrors.sol";
    import "./ILexPoolV1.sol";
    import "./IInterestRateModel.sol";
    import "./IFundingRateModel.sol";
    import "./TradingEnumsV1.sol";
    
    interface PoolAccountantStructs {
      // @note To be used for passing information in function calls
      struct PositionRegistrationParams {
        uint256 collateral;
        uint32 leverage;
        bool long;
        uint64 openPrice;
        uint64 tp;
      }
    
      struct PairFunding {
        // Slot 0
        int256 accPerOiLong; // 32 bytes -- Underlying Decimals
        // Slot 1
        int256 accPerOiShort; // 32 bytes -- Underlying Decimals
        // Slot 2
        uint256 lastUpdateTimestamp; // 32 bytes
      }
    
      struct TradeInitialAccFees {
        // Slot 0
        uint256 borrowIndex; // 32 bytes
        // Slot 1
        int256 funding; // 32 bytes -- underlying units -- Underlying Decimals
      }
    
      struct PairOpenInterest {
        // Slot 0
        uint256 long; // 32 bytes -- underlying units -- Dynamic open interest for long positions
        // Slot 1
        uint256 short; // 32 bytes -- underlying units -- Dynamic open interest for short positions
      }
    
      // This struct is not kept in storage
      struct PairFromTo {
        string from;
        string to;
      }
    
      struct Pair {
        // Slot 0
        uint16 id; // 02 bytes
        uint16 groupId; // 02 bytes
        uint16 feeId; // 02 bytes
        uint32 minLeverage; // 04 bytes
        uint32 maxLeverage; // 04 bytes
        uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
        // Slot 1
        uint256 maxPositionSize; // 32 bytes -- underlying units
        // Slot 2
        uint256 maxGain; // 32 bytes -- underlying units
        // Slot 3
        uint256 maxOpenInterest; // 32 bytes -- Underlying units
        // Slot 4
        uint256 maxSkew; // 32 bytes -- underlying units
        // Slot 5
        uint256 minOpenFee; // 32 bytes -- underlying units. MAX_UINT means use the default group level value
        // Slot 6
        uint256 minPerformanceFee; // 32 bytes -- underlying units
      }
    
      struct Group {
        // Slot 0
        uint16 id; // 02 bytes
        uint32 minLeverage; // 04 bytes
        uint32 maxLeverage; // 04 bytes
        uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
        // Slot 1
        uint256 maxPositionSize; // 32 bytes (Underlying units)
        // Slot 2
        uint256 minOpenFee; // 32 bytes (Underlying uints). MAX_UINT means use the default global level value
      }
    
      struct Fee {
        // Slot 0
        uint16 id; // 02 bytes
        uint32 openFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
        uint32 closeFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
        uint32 performanceFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of performance)
      }
    }
    
    interface PoolAccountantEvents is PoolAccountantStructs {
      event PairAdded(
        uint256 indexed id,
        string indexed from,
        string indexed to,
        Pair pair
      );
      event PairUpdated(uint256 indexed id, Pair pair);
    
      event GroupAdded(uint256 indexed id, string indexed groupName, Group group);
      event GroupUpdated(uint256 indexed id, Group group);
    
      event FeeAdded(uint256 indexed id, string indexed name, Fee fee);
      event FeeUpdated(uint256 indexed id, Fee fee);
    
      event TradeInitialAccFeesStored(
        bytes32 indexed positionId,
        uint256 borrowIndex,
        // uint256 rollover,
        int256 funding
      );
    
      event AccrueFunding(
        uint256 indexed pairId,
        int256 valueLong,
        int256 valueShort
      );
    
      event ProtocolFundingShareAccrued(
        uint16 indexed pairId,
        uint256 protocolFundingShare
      );
      // event AccRolloverFeesStored(uint256 pairIndex, uint256 value);
    
      event FeesCharged(
        bytes32 indexed positionId,
        address indexed trader,
        uint16 indexed pairId,
        PositionRegistrationParams positionRegistrationParams,
        //        bool long,
        //        uint256 collateral, // Underlying Decimals
        //        uint256 leverage,
        int256 profitPrecision, // PRECISION
        uint256 interest,
        int256 funding, // Underlying Decimals
        uint256 closingFee,
        uint256 tradeValue
      );
    
      event PerformanceFeeCharging(
        bytes32 indexed positionId,
        uint256 performanceFee
      );
    
      event MaxOpenInterestUpdated(uint256 pairIndex, uint256 maxOpenInterest);
    
      event AccrueInterest(
        uint256 cash,
        uint256 totalInterestNew,
        uint256 borrowIndexNew,
        uint256 interestShareNew
      );
    
      event Borrow(
        uint256 indexed pairId,
        uint256 borrowAmount,
        uint256 newTotalBorrows
      );
    
      event Repay(
        uint256 indexed pairId,
        uint256 repayAmount,
        uint256 newTotalBorrows
      );
    }
    
    interface IPoolAccountantFunctionality is
      PoolAccountantStructs,
      PoolAccountantEvents,
      LexErrors,
      TradingEnumsV1
    {
      function setTradeIncentivizer(address _tradeIncentivizer) external;
    
      function setMaxGainF(uint256 _maxGainF) external;
    
      function setFrm(IFundingRateModel _frm) external;
    
      function setMinOpenFee(uint256 min) external;
    
      function setLexPartF(uint256 partF) external;
    
      function setFundingRateMax(uint256 maxValue) external;
    
      function setLiquidationThresholdF(uint256 threshold) external;
    
      function setLiquidationFeeF(uint256 fee) external;
    
      function setIrm(IInterestRateModel _irm) external;
    
      function setIrmHard(IInterestRateModel _irm) external;
    
      function setInterestShareFactor(uint256 factor) external;
      
      function setFundingShareFactor(uint256 factor) external;
    
      function setBorrowRateMax(uint256 rate) external;
    
      function setMaxTotalBorrows(uint256 maxBorrows) external;
    
      function setMaxVirtualUtilization(uint256 _maxVirtualUtilization) external;
    
      function resetTradersPairGains(uint256 pairId) external;
    
      function addGroup(Group calldata _group) external;
    
      function updateGroup(Group calldata _group) external;
    
      function addFee(Fee calldata _fee) external;
    
      function updateFee(Fee calldata _fee) external;
    
      function addPair(Pair calldata _pair) external;
    
      function addPairs(Pair[] calldata _pairs) external;
    
      function updatePair(Pair calldata _pair) external;
    
      function readAndZeroReserves()
        external
        returns (uint256 accumulatedInterestShare,
                 uint256 accFundingShare);
    
      function registerOpenTrade(
        bytes32 positionId,
        address trader,
        uint16 pairId,
        uint256 collateral,
        uint32 leverage,
        bool long,
        uint256 tp,
        uint256 openPrice
      ) external returns (uint256 fee, uint256 lexPartFee);
    
      function registerCloseTrade(
        bytes32 positionId,
        address trader,
        uint16 pairId,
        PositionRegistrationParams calldata positionRegistrationParams,
        uint256 closePrice,
        PositionCloseType positionCloseType
      )
        external
        returns (
          uint256 closingFee,
          uint256 tradeValue,
          int256 profitPrecision,
          uint finalClosePrice
        );
    
      function registerUpdateTp(
        bytes32 positionId,
        address trader,
        uint16 pairId,
        uint256 collateral,
        uint32 leverage,
        bool long,
        uint256 openPrice,
        uint256 oldTriggerPrice,
        uint256 triggerPrice
      ) external;
    
      // function registerUpdateSl(
      //     address trader,
      //     uint256 pairIndex,
      //     uint256 index,
      //     uint256 collateral,
      //     uint256 leverage,
      //     bool long,
      //     uint256 openPrice,
      //     uint256 triggerPrice
      // ) external returns (uint256 fee);
    
      function accrueInterest()
        external
        returns (
          uint256 totalInterestNew,
          uint256 interestShareNew,
          uint256 borrowIndexNew
        );
    
      // Limited only for the LexPool
      function accrueInterest(
        uint256 availableCash
      )
        external
        returns (
          uint256 totalInterestNew,
          uint256 interestShareNew,
          uint256 borrowIndexNew
        );
    
      function getTradeClosingValues(
        bytes32 positionId,
        uint16 pairId,
        PositionRegistrationParams calldata positionRegistrationParams,
        uint256 closePrice,
        bool isLiquidation
      )
        external
        returns (
          uint256 tradeValue, // Underlying Decimals
          uint256 safeClosingFee,
          int256 profitPrecision,
          uint256 interest,
          int256 funding
        );
    
      function getTradeLiquidationPrice(
        bytes32 positionId,
        uint16 pairId,
        uint256 openPrice, // PRICE_SCALE (8)
        uint256 tp,
        bool long,
        uint256 collateral, // Underlying Decimals
        uint32 leverage
      )
        external
        returns (
          uint256 // PRICE_SCALE (8)
        );
    
      function calcTradeDynamicFees(
        bytes32 positionId,
        uint16 pairId,
        bool long,
        uint256 collateral,
        uint32 leverage,
        uint256 openPrice,
        uint256 tp
      ) external returns (uint256 interest, int256 funding);
    
      function unrealizedFunding() external view returns (int256);
    
      function totalBorrows() external view returns (uint256);
    
      function interestShare() external view returns (uint256);
      
      function fundingShare() external view returns (uint256);
    
      function totalReservesView() external view returns (uint256);
    
      function borrowsAndInterestShare()
        external
        view
        returns (uint256 totalBorrows, uint256 totalInterestShare);
    
      function pairTotalOpenInterest(
        uint256 pairIndex
      ) external view returns (int256);
    
      function pricePnL(
        uint256 pairId,
        uint256 price
      ) external view returns (int256);
    
      function getAllSupportedPairIds() external view returns (uint16[] memory);
    
      function getAllSupportedGroupsIds() external view returns (uint16[] memory);
    
      function getAllSupportedFeeIds() external view returns (uint16[] memory);
    }
    
    interface IPoolAccountantV1 is IPoolAccountantFunctionality {
      function totalBorrows() external view returns (uint256);
    
      function maxTotalBorrows() external view returns (uint256);
    
      function pairBorrows(uint256 pairId) external view returns (uint256);
    
      function groupBorrows(uint256 groupId) external view returns (uint256);
    
      function pairMaxBorrow(uint16 pairId) external view returns (uint256);
    
      function groupMaxBorrow(uint16 groupId) external view returns (uint256);
    
      function lexPool() external view returns (ILexPoolV1);
    
      function maxGainF() external view returns (uint256);
    
      function interestShareFactor() external view returns (uint256);
      
      function fundingShareFactor() external view returns (uint256);
    
      function frm() external view returns (IFundingRateModel);
    
      function irm() external view returns (IInterestRateModel);
    
      function pairs(uint16 pairId) external view returns (Pair memory);
    
      function groups(uint16 groupId) external view returns (Group memory);
    
      function fees(uint16 feeId) external view returns (Fee memory);
    
      function openInterestInPair(
        uint pairId
      ) external view returns (PairOpenInterest memory);
    
      function minOpenFee() external view returns (uint256);
    
      function liquidationThresholdF() external view returns (uint256);
    
      function liquidationFeeF() external view returns (uint256);
    
      function lexPartF() external view returns (uint256);
    
      function tradersPairGains(uint256 pairId) external view returns (int256);
    
      function calcBorrowAmount(
        uint256 collateral,
        uint256 leverage,
        bool long,
        uint256 openPrice,
        uint256 tp
      ) external pure returns (uint256);
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "../../AdministrationContracts/IContractRegistryBase.sol";
    import "./IGlobalLock.sol";
    
    interface IRegistryV1Functionality is IContractRegistryBase, IGlobalLock {
      // **** Locking mechanism ****
    
      function isTradersPortalAndLocker(
        address _address
      ) external view returns (bool);
    
      function isTriggersAndLocker(address _address) external view returns (bool);
    
      function isTradersPortalOrTriggersAndLocker(
        address _address
      ) external view returns (bool);
    }
    
    interface IRegistryV1 is IRegistryV1Functionality {
      // **** Public Storage params ****
    
      function feesManagers(address asset) external view returns (address);
    
      function orderBook() external view returns (address);
    
      function tradersPortal() external view returns (address);
    
      function triggers() external view returns (address);
    
      function tradeIntentsVerifier() external view returns (address);
    
      function liquidityIntentsVerifier() external view returns (address);
    
      function chipsIntentsVerifier() external view returns (address);
    
      function lexProxiesFactory() external view returns (address);
    
      function chipsFactory() external view returns (address);
    
      /**
       * @return An array of all supported trading floors
       */
      function getAllSupportedTradingFloors()
        external
        view
        returns (address[] memory);
    
      /**
       * @return An array of all supported settlement assets
       */
      function getSettlementAssetsForTradingFloor(
        address _tradingFloor
      ) external view returns (address[] memory);
    
      /**
       * @return The spender role address that is set for this chip
       */
      function getValidSpenderTargetForChipByRole(
        address chip,
        string calldata role
      ) external view returns (address);
    
      /**
       * @return the address of the valid 'burnHandler' for the chip
       */
      function validBurnHandlerForChip(
        address chip
      ) external view returns (address);
    
      /**
       * @return The address matching for the given role
       */
      function getDynamicRoleAddress(
        string calldata _role
      ) external view returns (address);
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "./TradingFloorStructsV1.sol";
    import "./IPoolAccountantV1.sol";
    import "./ILexPoolV1.sol";
    
    interface ITradingFloorV1Functionality is TradingFloorStructsV1 {
      function supportNewSettlementAsset(
        address _asset,
        address _lexPool,
        address _poolAccountant
      ) external;
    
      function getPositionTriggerInfo(
        bytes32 _positionId
      )
        external
        view
        returns (
          PositionPhase positionPhase,
          uint64 timestamp,
          uint16 pairId,
          bool long,
          uint32 spreadReductionF
        );
    
      function getPositionPortalInfo(
        bytes32 _positionId
      )
        external
        view
        returns (
          PositionPhase positionPhase,
          uint64 inPhaseSince,
          address positionTrader
        );
    
      function storePendingPosition(
        OpenOrderType _orderType,
        PositionRequestIdentifiers memory _requestIdentifiers,
        PositionRequestParams memory _requestParams,
        uint32 _spreadReductionF
      ) external returns (bytes32 positionId);
    
      function setOpenedPositionToMarketClose(
        bytes32 _positionId,
        uint64 _minPrice,
        uint64 _maxPrice
      ) external;
    
      function cancelPendingPosition(
        bytes32 _positionId,
        OpenOrderType _orderType,
        uint feeFraction
      ) external;
    
      function cancelMarketCloseForPosition(
        bytes32 _positionId,
        CloseOrderType _orderType,
        uint feeFraction
      ) external;
    
      function updatePendingPosition_openLimit(
        bytes32 _positionId,
        uint64 _minPrice,
        uint64 _maxPrice,
        uint64 _tp,
        uint64 _sl
      ) external;
    
      function openNewPosition_market(
        bytes32 _positionId,
        uint64 assetEffectivePrice,
        uint256 feeForCancellation
      ) external;
    
      function openNewPosition_limit(
        bytes32 _positionId,
        uint64 assetEffectivePrice,
        uint256 feeForCancellation
      ) external;
    
      function closeExistingPosition_Market(
        bytes32 _positionId,
        uint64 assetPrice,
        uint64 effectivePrice
      ) external;
    
      function closeExistingPosition_Limit(
        bytes32 _positionId,
        LimitTrigger limitTrigger,
        uint64 assetPrice,
        uint64 effectivePrice
      ) external;
    
      // Manage open trade
      function updateOpenedPosition(
        bytes32 _positionId,
        PositionField updateField,
        uint64 fieldValue,
        uint64 effectivePrice
      ) external;
    
      // Fees
      function collectFee(address _asset, FeeType _feeType, address _to) external;
    }
    
    interface ITradingFloorV1 is ITradingFloorV1Functionality {
      function PRECISION() external pure returns (uint);
    
      // *** Views ***
    
      function pairTradersArray(
        address _asset,
        uint _pairIndex
      ) external view returns (address[] memory);
    
      function generatePositionHashId(
        address settlementAsset,
        address trader,
        uint16 pairId,
        uint32 index
      ) external pure returns (bytes32 hashId);
    
      // *** Public Storage addresses ***
    
      function lexPoolForAsset(address asset) external view returns (ILexPoolV1);
    
      function poolAccountantForAsset(
        address asset
      ) external view returns (IPoolAccountantV1);
    
      function registry() external view returns (address);
    
      // *** Public Storage params ***
    
      function positionsById(bytes32 id) external view returns (Position memory);
    
      function positionIdentifiersById(
        bytes32 id
      ) external view returns (PositionIdentifiers memory);
    
      function positionLimitsInfoById(
        bytes32 id
      ) external view returns (PositionLimitsInfo memory);
    
      function triggerPricesById(
        bytes32 id
      ) external view returns (PositionTriggerPrices memory);
    
      function pairTradersInfo(
        address settlementAsset,
        address trader,
        uint pairId
      ) external view returns (PairTraderInfo memory);
    
      function spreadReductionsP(uint) external view returns (uint);
    
      function maxSlF() external view returns (uint);
    
      function maxTradesPerPair() external view returns (uint);
    
      function maxSanityProfitF() external view returns (uint);
    
      function feesMap(
        address settlementAsset,
        FeeType feeType
      ) external view returns (uint256);
    }

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

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.24;
    
    interface LexPoolAdminEnums {
      enum LexPoolAddressesEnum {
        none,
        poolAccountant,
        pnlRole
      }
    
      enum LexPoolNumbersEnum {
        none,
        maxExtraWithdrawalAmountF,
        epochsDelayDeposit,
        epochsDelayRedeem,
        epochDuration,
        minDepositAmount
      }
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    interface TradingEnumsV1 {
      enum PositionPhase {
        NONE,
        OPEN_MARKET,
        OPEN_LIMIT,
        OPENED,
        CLOSE_MARKET,
        CLOSED
      }
    
      enum OpenOrderType {
        NONE,
        MARKET,
        LIMIT
      }
      enum CloseOrderType {
        NONE,
        MARKET
      }
      enum FeeType {
        NONE,
        OPEN_FEE,
        CLOSE_FEE,
        TRIGGER_FEE
      }
      enum LimitTrigger {
        NONE,
        TP,
        SL,
        LIQ
      }
      enum PositionField {
        NONE,
        TP,
        SL
      }
    
      enum PositionCloseType {
        NONE,
        TP,
        SL,
        LIQ,
        MARKET
      }
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "./TradingEnumsV1.sol";
    
    interface TradingFloorStructsV1 is TradingEnumsV1 {
      enum AdminNumericParam {
        NONE,
        MAX_TRADES_PER_PAIR,
        MAX_SL_F,
        MAX_SANITY_PROFIT_F
      }
    
      /**
       * @dev Memory struct for identifiers
       */
      struct PositionRequestIdentifiers {
        address trader;
        uint16 pairId;
        address settlementAsset;
        uint32 positionIndex;
      }
    
      struct PositionRequestParams {
        bool long;
        uint256 collateral; // Settlement Asset Decimals
        uint32 leverage;
        uint64 minPrice; // PRICE_SCALE
        uint64 maxPrice; // PRICE_SCALE
        uint64 tp; // PRICE_SCALE
        uint64 sl; // PRICE_SCALE
        uint64 tpByFraction; // FRACTION_SCALE
        uint64 slByFraction; // FRACTION_SCALE
      }
    
      /**
       * @dev Storage struct for identifiers
       */
      struct PositionIdentifiers {
        // Slot 0
        address settlementAsset; // 20 bytes
        uint16 pairId; // 02 bytes
        uint32 index; // 04 bytes
        // Slot 1
        address trader; // 20 bytes
      }
    
      struct Position {
        // Slot 0
        uint collateral; // 32 bytes -- Settlement Asset Decimals
        // Slot 1
        PositionPhase phase; // 01 bytes
        uint64 inPhaseSince; // 08 bytes
        uint32 leverage; // 04 bytes
        bool long; // 01 bytes
        uint64 openPrice; // 08 bytes -- PRICE_SCALE (8)
        uint32 spreadReductionF; // 04 bytes -- FRACTION_SCALE (5)
      }
    
      /**
       * Holds the non liquidation limits for the position
       */
      struct PositionLimitsInfo {
        uint64 tpLastUpdated; // 08 bytes -- timestamp
        uint64 slLastUpdated; // 08 bytes -- timestamp
        uint64 tp; // 08 bytes -- PRICE_SCALE (8)
        uint64 sl; // 08 bytes -- PRICE_SCALE (8)
      }
    
      /**
       * Holds the prices for opening (and market closing) of a position
       */
      struct PositionTriggerPrices {
        uint64 minPrice; // 08 bytes -- PRICE_SCALE
        uint64 maxPrice; // 08 bytes -- PRICE_SCALE
        uint64 tpByFraction; // 04 bytes -- FRACTION_SCALE
        uint64 slByFraction; // 04 bytes -- FRACTION_SCALE
      }
    
      /**
       * @dev administration struct, used to keep tracks on the 'PairTraders' list and
       *      to limit the amount of positions a trader can have
       */
      struct PairTraderInfo {
        uint32 positionsCounter; // 04 bytes
        uint32 positionInArray; // 04 bytes (the index + 1)
        // Note : Can add more fields here
      }
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "../../AdministrationContracts/AcceptableImplementationClaimableAdmin.sol";
    
    /**
     * @title RegistryProxy
     * @dev Used as the contracts registry brain of the Lynx platform
     */
    contract RegistryProxy is AcceptableImplementationClaimableAdmin {
      constructor() AcceptableImplementationClaimableAdmin(msg.sender) {}
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "../../AdministrationContracts/AcceptableImplementationClaimableAdminStorage.sol";
    
    /**
     * @title RegistryStorage
     * @dev Storage contract for the Registry
     */
    contract RegistryStorage is AcceptableImplementationClaimableAdminStorage {
      uint256 public constant VERSION_SCALE = 1000; // 1,000 = 1.00, 1,120 = 1.12
    
      // ***** Locking mechanism *****
    
      // System lock
      address public systemLockOwner;
    
      // Address => is allowed to lock the system
      mapping(address => bool) public validSystemLockOwners;
    
      // ***** Versioning mechanism *****
    
      // contract name hash => latest version number
      mapping(bytes32 => uint256) public latestVersions;
    
      // version => (contract name hash => implementation)
      mapping(uint256 => mapping(bytes32 => address)) public implementations;
    
      // ***** Trading Floors *****
    
      // trading floor => is supported
      mapping(address => bool) public isTradingFloorSupported;
    
      // all supported trading floors
      address[] public supportedTradingFloors;
    
      // trading floor => supported settlement assets lists
      mapping(address => address[]) public settlementAssetsForTradingFloor;
    
      // ***** Roles mechanism *****
    
      // asset => feesManager
      mapping(address => address) public feesManagers;
    
      // role hash => address
      mapping(bytes32 => address) public dynamicRoleAddresses;
    
      address public orderBook;
    
      address public tradersPortal;
    
      address public triggers;
    
      address public tradeIntentsVerifier;
    
      address public liquidityIntentsVerifier;
    
      address public chipsIntentsVerifier;
    
      // ***** Chips *****
    
      // chip => role (hash) => spender
      mapping(address => mapping(bytes32 => address))
        public validSpenderTargetForChipByRole;
    
      // chip => valid burn handler
      mapping(address => address) public validBurnHandlerForChip;
    
      // ***** Factories *****
    
      address public lexProxiesFactory;
    
      address public chipsFactory;
    }

    // SPDX-License-Identifier: BUSL-1.1
    pragma solidity ^0.8.24;
    
    import "../interfaces/IRegistryV1.sol";
    import "../interfaces/ITradingFloorV1.sol";
    import "../interfaces/ChipEnumsV1.sol";
    
    import "./RegistryStorage.sol";
    import "./RegistryProxy.sol";
    
    /**
     * @title RegistryV1
     * @dev Main administration contract for the Lynx platform, keeping track of all the system's contracts and their versions
     */
    contract RegistryV1 is RegistryStorage, IRegistryV1Functionality {
      event AddressUpdated(string indexed name, address a);
      event NewVersionPublished(
        uint256 indexed version,
        bytes32 indexed contractNameHash,
        address contractImplementation
      );
      event FeesManagerSet(address indexed asset, address indexed feesManager);
    
      event TradingFloorSupported(address indexed tradingFloor);
      event SettlementAssetForTradingFloorAdded(
        address indexed tradingFloor,
        address indexed settlementAsset,
        address indexed lexPool,
        address poolAccountant
      );
    
      event ValidChipSpenderTargetByRoleSet(
        address indexed chip,
        string indexed role,
        address indexed spender
      );
      event ValidChipBurnHandlerSet(
        address indexed chip,
        address indexed burnHandler
      );
    
      // ***** Initialization functions *****
    
      /**
       * @notice Part of the Proxy mechanism
       */
      function _become(RegistryProxy registryProxy) public {
        require(msg.sender == registryProxy.admin(), "!proxy.admin");
        require(registryProxy._acceptImplementation() == 0, "fail");
      }
    
      // ***** Global Lock functions *****
    
      modifier onlyLockOwner() {
        require(msg.sender == systemLockOwner, "!LockOwner");
        _;
      }
    
      function lock() external override {
        require(validSystemLockOwners[msg.sender], "!ValidLocker");
        require(systemLockOwner == address(0), "AlreadyLocked");
        systemLockOwner = msg.sender;
      }
    
      function freeLock() external override onlyLockOwner {
        systemLockOwner = address(0);
      }
    
      function isTradersPortalAndLocker(
        address _address
      ) external view returns (bool) {
        return (systemLockOwner == _address) && (_address == tradersPortal);
      }
    
      function isTriggersAndLocker(address _address) external view returns (bool) {
        return (systemLockOwner == _address) && (_address == triggers);
      }
    
      function isTradersPortalOrTriggersAndLocker(
        address _address
      ) external view returns (bool) {
        return
          (systemLockOwner == _address) &&
          (_address == tradersPortal || _address == triggers);
      }
    
      // ***** Views *****
    
      /**
       * @return true if the given implementation is valid for the given proxy name
       */
      function isImplementationValidForProxy(
        bytes32 proxyNameHash,
        address _implementation
      ) external view returns (bool) {
        require(_implementation != address(0), "ZERO_ADDRESS");
        address latestImplementation = getLatestImplementationForProxyByHashInternal(
            proxyNameHash
          );
        return latestImplementation == _implementation;
      }
    
      /**
       * @return The address of the latest implementation version for the given proxy name hash
       */
      function getLatestImplementationForProxyByHash(
        bytes32 proxyNameHash
      ) external view returns (address) {
        return getLatestImplementationForProxyByHashInternal(proxyNameHash);
      }
    
      /**
       * @return The address of the latest implementation version for the given proxy name
       */
      function getLatestImplementationForProxyByName(
        string calldata proxyName
      ) external view returns (address) {
        bytes32 nameHash = keccak256(abi.encodePacked(proxyName));
    
        return getLatestImplementationForProxyByHashInternal(nameHash);
      }
    
      /**
       * @return An array of all supported trading floors
       */
      function getAllSupportedTradingFloors()
        external
        view
        returns (address[] memory)
      {
        return supportedTradingFloors;
      }
    
      /**
       * @return An array of all supported settlement assets
       */
      function getSettlementAssetsForTradingFloor(
        address _tradingFloor
      ) external view returns (address[] memory) {
        return settlementAssetsForTradingFloor[_tradingFloor];
      }
    
      /**
       * @return The address matching for the given role
       */
      function getDynamicRoleAddress(
        string calldata _role
      ) external view returns (address) {
        bytes32 roleHash = keccak256(abi.encodePacked(_role));
        return dynamicRoleAddresses[roleHash];
      }
    
      /**
       * @return The spender role address that is set for this chip
       */
      function getValidSpenderTargetForChipByRole(
        address chip,
        string calldata role
      ) external view returns (address) {
        bytes32 roleHash = keccak256(abi.encodePacked(role));
        return validSpenderTargetForChipByRole[chip][roleHash];
      }
    
      // ***** Admin Functions *****
    
      /**
       * Setter for any dynamic roles addresses
       */
      function setDynamicRoleAddress(
        string calldata _role,
        address _address
      ) external onlyAdmin {
        bytes32 roleHash = keccak256(abi.encodePacked(_role));
        dynamicRoleAddresses[roleHash] = _address;
        emit AddressUpdated(_role, _address);
      }
    
      /**
       * Setter for the 'OrderBook' contract
       */
      function setOrderBook(address _orderBook) external onlyAdmin {
        updateLockerAddressInternal(orderBook, _orderBook, "orderBook");
        orderBook = _orderBook;
      }
    
      /**
       * Setter for the 'TradersPortal' contract
       */
      function setTradersPortal(address _tradersPortal) external onlyAdmin {
        updateLockerAddressInternal(tradersPortal, _tradersPortal, "tradersPortal");
        tradersPortal = _tradersPortal;
      }
    
      /**
       * Setter for the 'Triggers' contract
       */
      function setTriggers(address _triggers) external onlyAdmin {
        updateLockerAddressInternal(triggers, _triggers, "triggers");
        triggers = _triggers;
      }
    
      /**
       * Setter for the 'TradeIntentsVerifier' contract
       */
      function setTradeIntentsVerifier(
        address _tradeIntentsVerifier
      ) external onlyAdmin {
        tradeIntentsVerifier = _tradeIntentsVerifier;
        emit AddressUpdated("tradeIntentsVerifier", _tradeIntentsVerifier);
      }
    
      /**
       * Setter for the 'LiquidityIntentsVerifier' contract
       */
      function setLiquidityIntentsVerifier(
        address _liquidityIntentsVerifier
      ) external onlyAdmin {
        liquidityIntentsVerifier = _liquidityIntentsVerifier;
        emit AddressUpdated("liquidityIntentsVerifier", _liquidityIntentsVerifier);
      }
    
      /**
       * Setter for the 'ChipsIntentsVerifier' contract
       */
      function setChipsIntentsVerifier(
        address _chipsIntentsVerifier
      ) external onlyAdmin {
        chipsIntentsVerifier = _chipsIntentsVerifier;
        emit AddressUpdated("chipsIntentsVerifier", _chipsIntentsVerifier);
      }
    
      /**
       * Sets lex proxies factory role for a specific asset
       */
      function setLexProxiesFactory(address _lexProxiesFactory) external onlyAdmin {
        lexProxiesFactory = _lexProxiesFactory;
        emit AddressUpdated("lexProxiesFactory", _lexProxiesFactory);
      }
    
      /**
       * Sets chips factory role for a specific asset
       */
      function setChipsFactory(address _chipsFactory) external onlyAdmin {
        chipsFactory = _chipsFactory;
        emit AddressUpdated("chipsFactory", _chipsFactory);
      }
    
      /**
       * Sets fee manager role for a specific asset
       */
      function setFeesManager(
        address asset,
        address feesManager
      ) external onlyAdmin {
        feesManagers[asset] = feesManager;
    
        emit FeesManagerSet(asset, feesManager);
      }
    
      /**
       * Allows setting/unsetting of valid spender targets for chips by specific roles
       */
      function setValidChipSpenderTargetByRole(
        address chip,
        string calldata role,
        address spender
      ) external onlyAdmin {
        setValidChipSpenderByRoleInternal(chip, role, spender);
      }
    
      /**
       * Allows setting/unsetting of valid burn handlers for chips
       */
      function setValidChipBurnHandler(
        address chip,
        address burnHandler
      ) external onlyAdmin {
        setValidChipBurnHandlerInternal(chip, burnHandler);
      }
    
      /**
       * Publish version for a single contract
       */
      function publishNewSystemVersionSingle(
        uint256 versionToPublish,
        bytes32 contractNameHash,
        address contractImplementation
      ) external onlyAdmin {
        publishNewSystemVersionSingleInternal(
          versionToPublish,
          contractNameHash,
          contractImplementation
        );
      }
    
      /**
       * Publish version for multiple contracts
       */
      function publishNewSystemVersionBatch(
        uint256 versionToPublish,
        bytes32[] calldata contractNameHashes,
        address[] calldata contractImplementations
      ) external onlyAdmin {
        require(
          contractNameHashes.length == contractImplementations.length,
          "Arrays must be 1:1"
        );
    
        for (uint256 i = 0; i < contractNameHashes.length; i++) {
          bytes32 contractNameHash = contractNameHashes[i];
          address contractImplementation = contractImplementations[i];
    
          publishNewSystemVersionSingleInternal(
            versionToPublish,
            contractNameHash,
            contractImplementation
          );
        }
      }
    
      /**
       * Supports a new Trading floor contract
       */
      function supportTradingFloor(address _tradingFloor) external onlyAdmin {
        isTradingFloorSupported[_tradingFloor] = true;
    
        supportedTradingFloors.push(_tradingFloor);
    
        emit TradingFloorSupported(_tradingFloor);
      }
    
      /**
       * Adds a new settlement asset for a trading floor
       */
      function addNewSettlementAssetInTradingFloor(
        address _tradingFloor,
        address _asset,
        address _lexPool,
        address _poolAccountant
      ) external onlyAdmin {
        require(
          _asset != address(0) &&
            _lexPool != address(0) &&
            _poolAccountant != address(0),
          "CANNOT_BE_ZERO_ADDRESS"
        );
    
        require(
          _asset == address(ILexPoolV1(_lexPool).underlying()),
          "LEX_UNDERLYING_MISMATCH"
        );
    
        require(
          address(IPoolAccountantV1(_poolAccountant).lexPool()) == _lexPool,
          "LEX_POOL_MISMATCH"
        );
    
        // Adds the LexPool as a valid system locker
        validSystemLockOwners[_lexPool] = true;
    
        // Add the settlement asset to the TradingFloor's list
        settlementAssetsForTradingFloor[_tradingFloor].push(_asset);
    
        // Add the settlement asset in the TradingFloor itself
        ITradingFloorV1(_tradingFloor).supportNewSettlementAsset(
          _asset,
          _lexPool,
          _poolAccountant
        );
    
        // Set the TradingFloor as a valid spender for the chip
        string memory tradingFloorRole = "TradingFloor";
        setValidChipSpenderByRoleInternal(_asset, tradingFloorRole, _tradingFloor);
    
        // Set the LexPool as a valid spender for the chip
        string memory lexPoolRole = "LexPool";
        setValidChipSpenderByRoleInternal(_asset, lexPoolRole, _lexPool);
    
        // Set the ChipsIntentsVerifier as a valid spender for the chip
        string memory chipsIntentsVerifierRole = "ChipsIntentsVerifier";
        setValidChipSpenderByRoleInternal(
          _asset,
          chipsIntentsVerifierRole,
          chipsIntentsVerifier
        );
    
        // Event
        emit SettlementAssetForTradingFloorAdded(
          _tradingFloor,
          _asset,
          _lexPool,
          _poolAccountant
        );
      }
    
      // ***** Internal Views *****
    
      function getLatestImplementationForProxyByHashInternal(
        bytes32 proxyNameHash
      ) internal view returns (address) {
        uint256 latestVersionNumber = latestVersions[proxyNameHash];
        return implementations[latestVersionNumber][proxyNameHash];
      }
    
      // ***** Internal Logic *****
    
      /**
       * Handles version publishing for a single versioned contract
       */
      function publishNewSystemVersionSingleInternal(
        uint256 versionToPublish,
        bytes32 contractNameHash,
        address contractImplementation
      ) internal {
        uint256 latestSystemVersion = latestVersions[contractNameHash];
        require(
          versionToPublish > latestSystemVersion,
          "MUST_PUBLISH_NEWER_VERSION"
        );
        require(contractImplementation != address(0), "IMPLEMENTATION_ZERO");
    
        latestVersions[contractNameHash] = versionToPublish;
        implementations[versionToPublish][
          contractNameHash
        ] = contractImplementation;
    
        emit NewVersionPublished(
          versionToPublish,
          contractNameHash,
          contractImplementation
        );
      }
    
      /**
       * Utility function to handle the "valid lockers" mechanism
       */
      function updateLockerAddressInternal(
        address _currentLocker,
        address _newLocker,
        string memory name
      ) internal {
        require(_newLocker != address(0), "CANNOT_BE_ZERO_ADDRESS");
        validSystemLockOwners[_currentLocker] = false;
        validSystemLockOwners[_newLocker] = true;
        emit AddressUpdated(name, _newLocker);
      }
    
      function setValidChipSpenderByRoleInternal(
        address chip,
        string memory role,
        address spender
      ) internal {
        bytes32 roleHash = keccak256(abi.encodePacked(role));
        address currentSpenderByRole = validSpenderTargetForChipByRole[chip][
          roleHash
        ];
    
        // Sanity
        require(currentSpenderByRole != spender, "ALREADY_SET");
    
        // Storage update
        validSpenderTargetForChipByRole[chip][roleHash] = spender;
    
        // Event
        emit ValidChipSpenderTargetByRoleSet(chip, role, spender);
      }
    
      function setValidChipBurnHandlerInternal(
        address chip,
        address burnHandler
      ) internal {
        address currentBurnHandler = validBurnHandlerForChip[chip];
    
        // Sanity
        require(currentBurnHandler != burnHandler, "ALREADY_SET");
    
        // Storage update
        validBurnHandlerForChip[chip] = burnHandler;
    
        // Event
        emit ValidChipBurnHandlerSet(chip, burnHandler);
      }
    }

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

    Context size (optional):