APE Price: $0.17 (-3.60%)

Contract

0xE79b82669862EED0E247344747C3f044b808bcAe

Overview

APE Balance

Apechain LogoApechain LogoApechain Logo0 APE

APE Value

$0.00

More Info

Private Name Tags

Multichain Info

N/A
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
273431712025-11-12 16:59:2978 days ago1762966769  Contract Creation0 APE

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GNSReader

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 750 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../interfaces/IGNSMultiCollatDiamond.sol";
import "../interfaces/IERC20.sol";

/**
 * @dev Miscellaneous reader functions for GNS Multi-Collateral Diamond
 */
contract GNSReader {
    struct FeeTierOutput {
        IFeeTiersUtils.TraderInfo traderInfo;
        IFeeTiers.GnsStakingInfo gnsStakingInfo;
        IFeeTiersUtils.TraderDailyInfo traderDailyInfoLastUpdated;
        IFeeTiersUtils.TraderDailyInfo traderDailyInfoCurrent;
        IFeeTiersUtils.TraderDailyInfo traderDailyInfoExpired;
        IFeeTiersUtils.TraderEnrollment traderEnrollment;
        uint224 unclaimedPoints;
    }

    struct UserInfoOutput {
        uint256[] balances;
        uint256[] allowances;
        bool protectionCloseFactorWhitelist;
        IPriceImpact.UserPriceImpact[] userPriceImpacts;
        FeeTierOutput feeTierOutput;
        ITradingStorage.PendingOrder[] pendingOrders;
    }

    function getAllUserInfo(
        IGNSMultiCollatDiamond _diamond,
        address _user,
        address[] calldata _tokens
    ) external view returns (UserInfoOutput memory userInfo) {
        (userInfo.balances, userInfo.allowances) = getBalancesAndAllowances(address(_diamond), _user, _tokens);
        userInfo.protectionCloseFactorWhitelist = getProtectionCloseFactorWhitelist(_diamond, _user);
        userInfo.userPriceImpacts = getUserPriceImpact(_diamond, _user);
        userInfo.feeTierOutput = getUserTraderFeeTiers(_diamond, _user);
        userInfo.pendingOrders = getPendingOrders(_diamond, _user);

        return userInfo;
    }

    /// @dev Get balances and allowances for multiple tokens for a given user and diamond address
    function getBalancesAndAllowances(
        address _diamond,
        address _user,
        address[] calldata _tokens
    ) public view returns (uint256[] memory balances, uint256[] memory allowances) {
        uint256 length = _tokens.length;
        balances = new uint256[](length);
        allowances = new uint256[](length);

        for (uint256 i; i < length; ++i) {
            IERC20 token = IERC20(_tokens[i]);
            balances[i] = token.balanceOf(_user);
            allowances[i] = token.allowance(_user, _diamond);
        }
    }

    /// @dev fetch protectionCloseFactorWhitelist status for a user
    function getProtectionCloseFactorWhitelist(
        IGNSMultiCollatDiamond _diamond,
        address _user
    ) public view returns (bool) {
        return _diamond.getProtectionCloseFactorWhitelist(_user);
    }

    /// @dev fetch userPriceImpact for all pairs
    function getUserPriceImpact(
        IGNSMultiCollatDiamond _diamond,
        address _user
    ) public view returns (IPriceImpact.UserPriceImpact[] memory) {
        uint256 pairs = _diamond.pairsCount();
        IPriceImpact.UserPriceImpact[] memory userPriceImpacts = new IPriceImpact.UserPriceImpact[](pairs);

        for (uint256 i; i < pairs; ++i) {
            userPriceImpacts[i] = _diamond.getUserPriceImpact(_user, i);
        }

        return userPriceImpacts;
    }

    /// @dev fetch all fee tiers related info for a user
    function getUserTraderFeeTiers(
        IGNSMultiCollatDiamond _diamond,
        address _user
    ) public view returns (FeeTierOutput memory output) {
        uint32 currentDay = _getCurrentDay();

        output.traderInfo = _diamond.getFeeTiersTraderInfo(_user);

        output.gnsStakingInfo = _diamond.getGnsStakingInfo(_user);
        output.traderDailyInfoLastUpdated = _diamond.getFeeTiersTraderDailyInfo(
            _user,
            output.traderInfo.lastDayUpdated
        );
        output.traderDailyInfoCurrent = _diamond.getFeeTiersTraderDailyInfo(_user, currentDay);
        output.traderDailyInfoExpired = _diamond.getFeeTiersTraderDailyInfo(_user, currentDay - 30);
        output.traderEnrollment = _diamond.getTraderFeeTiersEnrollment(_user);
        output.unclaimedPoints = _diamond.getTraderUnclaimedPoints(_user);

        return output;
    }

    /// @dev fetch expired points for multiple days for a user
    function getExpiredPointsForDays(
        IGNSMultiCollatDiamond _diamond,
        address _user,
        uint32[] calldata _days
    ) public view returns (uint224[] memory expiredPoints) {
        expiredPoints = new uint224[](_days.length);

        for (uint256 i; i < _days.length; ++i) {
            IFeeTiersUtils.TraderDailyInfo memory traderDailyInfoExpired = _diamond.getFeeTiersTraderDailyInfo(
                _user,
                _days[i]
            );
            expiredPoints[i] = traderDailyInfoExpired.points;
        }

        return expiredPoints;
    }

    /// @dev fetch all pending orders for a user
    function getPendingOrders(
        IGNSMultiCollatDiamond _diamond,
        address _user
    ) public view returns (ITradingStorage.PendingOrder[] memory) {
        ITradingStorage.Counter memory counter = _diamond.getCounters(_user, ITradingStorage.CounterType.PENDING_ORDER);
        ITradingStorage.PendingOrder[] memory pendingOrders = new ITradingStorage.PendingOrder[](counter.openCount);

        if (counter.openCount == 0) {
            return pendingOrders;
        }

        uint256 limitIndex = counter.currentIndex > 100 ? counter.currentIndex - 100 : 0;

        uint256 curr;
        for (uint256 i = counter.currentIndex; i > limitIndex; --i) {
            ITradingStorage.PendingOrder memory order = _diamond.getPendingOrder(
                ITradingStorage.Id({user: _user, index: uint32(i - 1)})
            );

            if (!order.isOpen) continue;

            // if order open
            pendingOrders[curr++] = order;

            if (curr >= counter.openCount) {
                break;
            }
        }
        return pendingOrders;
    }

    function _getCurrentDay() internal view returns (uint32) {
        return uint32(block.timestamp / 1 days);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {CBORChainlink} from "./vendor/CBORChainlink.sol";
import {BufferChainlink} from "./vendor/BufferChainlink.sol";

/**
 * @title Library for common Chainlink functions
 * @dev Uses imported CBOR library for encoding to buffer
 */
library Chainlink {
  uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase

  using CBORChainlink for BufferChainlink.buffer;

  struct Request {
    bytes32 id;
    address callbackAddress;
    bytes4 callbackFunctionId;
    uint256 nonce;
    BufferChainlink.buffer buf;
  }

  /**
   * @notice Initializes a Chainlink request
   * @dev Sets the ID, callback address, and callback function signature on the request
   * @param self The uninitialized request
   * @param jobId The Job Specification ID
   * @param callbackAddr The callback address
   * @param callbackFunc The callback function signature
   * @return The initialized request
   */
  function initialize(
    Request memory self,
    bytes32 jobId,
    address callbackAddr,
    bytes4 callbackFunc
  ) internal pure returns (Chainlink.Request memory) {
    BufferChainlink.init(self.buf, defaultBufferSize);
    self.id = jobId;
    self.callbackAddress = callbackAddr;
    self.callbackFunctionId = callbackFunc;
    return self;
  }

  /**
   * @notice Sets the data for the buffer without encoding CBOR on-chain
   * @dev CBOR can be closed with curly-brackets {} or they can be left off
   * @param self The initialized request
   * @param data The CBOR data
   */
  function setBuffer(Request memory self, bytes memory data) internal pure {
    BufferChainlink.init(self.buf, data.length);
    BufferChainlink.append(self.buf, data);
  }

  /**
   * @notice Adds a string value to the request with a given key name
   * @param self The initialized request
   * @param key The name of the key
   * @param value The string value to add
   */
  function add(
    Request memory self,
    string memory key,
    string memory value
  ) internal pure {
    self.buf.encodeString(key);
    self.buf.encodeString(value);
  }

  /**
   * @notice Adds a bytes value to the request with a given key name
   * @param self The initialized request
   * @param key The name of the key
   * @param value The bytes value to add
   */
  function addBytes(
    Request memory self,
    string memory key,
    bytes memory value
  ) internal pure {
    self.buf.encodeString(key);
    self.buf.encodeBytes(value);
  }

  /**
   * @notice Adds a int256 value to the request with a given key name
   * @param self The initialized request
   * @param key The name of the key
   * @param value The int256 value to add
   */
  function addInt(
    Request memory self,
    string memory key,
    int256 value
  ) internal pure {
    self.buf.encodeString(key);
    self.buf.encodeInt(value);
  }

  /**
   * @notice Adds a uint256 value to the request with a given key name
   * @param self The initialized request
   * @param key The name of the key
   * @param value The uint256 value to add
   */
  function addUint(
    Request memory self,
    string memory key,
    uint256 value
  ) internal pure {
    self.buf.encodeString(key);
    self.buf.encodeUInt(value);
  }

  /**
   * @notice Adds an array of strings to the request with a given key name
   * @param self The initialized request
   * @param key The name of the key
   * @param values The array of string values to add
   */
  function addStringArray(
    Request memory self,
    string memory key,
    string[] memory values
  ) internal pure {
    self.buf.encodeString(key);
    self.buf.startArray();
    for (uint256 i = 0; i < values.length; i++) {
      self.buf.encodeString(values[i]);
    }
    self.buf.endSequence();
  }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);

  function approve(address spender, uint256 value) external returns (bool success);

  function balanceOf(address owner) external view returns (uint256 balance);

  function decimals() external view returns (uint8 decimalPlaces);

  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);

  function increaseApproval(address spender, uint256 subtractedValue) external;

  function name() external view returns (string memory tokenName);

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

  function totalSupply() external view returns (uint256 totalTokensIssued);

  function transfer(address to, uint256 value) external returns (bool success);

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  ) external returns (bool success);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool success);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @dev A library for working with mutable byte buffers in Solidity.
 *
 * Byte buffers are mutable and expandable, and provide a variety of primitives
 * for writing to them. At any time you can fetch a bytes object containing the
 * current contents of the buffer. The bytes object should not be stored between
 * operations, as it may change due to resizing of the buffer.
 */
library BufferChainlink {
  /**
   * @dev Represents a mutable buffer. Buffers have a current value (buf) and
   *      a capacity. The capacity may be longer than the current value, in
   *      which case it can be extended without the need to allocate more memory.
   */
  struct buffer {
    bytes buf;
    uint256 capacity;
  }

  /**
   * @dev Initializes a buffer with an initial capacity.
   * @param buf The buffer to initialize.
   * @param capacity The number of bytes of space to allocate the buffer.
   * @return The buffer, for chaining.
   */
  function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) {
    if (capacity % 32 != 0) {
      capacity += 32 - (capacity % 32);
    }
    // Allocate space for the buffer data
    buf.capacity = capacity;
    assembly {
      let ptr := mload(0x40)
      mstore(buf, ptr)
      mstore(ptr, 0)
      mstore(0x40, add(32, add(ptr, capacity)))
    }
    return buf;
  }

  /**
   * @dev Initializes a new buffer from an existing bytes object.
   *      Changes to the buffer may mutate the original value.
   * @param b The bytes object to initialize the buffer with.
   * @return A new buffer.
   */
  function fromBytes(bytes memory b) internal pure returns (buffer memory) {
    buffer memory buf;
    buf.buf = b;
    buf.capacity = b.length;
    return buf;
  }

  function resize(buffer memory buf, uint256 capacity) private pure {
    bytes memory oldbuf = buf.buf;
    init(buf, capacity);
    append(buf, oldbuf);
  }

  function max(uint256 a, uint256 b) private pure returns (uint256) {
    if (a > b) {
      return a;
    }
    return b;
  }

  /**
   * @dev Sets buffer length to 0.
   * @param buf The buffer to truncate.
   * @return The original buffer, for chaining..
   */
  function truncate(buffer memory buf) internal pure returns (buffer memory) {
    assembly {
      let bufptr := mload(buf)
      mstore(bufptr, 0)
    }
    return buf;
  }

  /**
   * @dev Writes a byte string to a buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param off The start offset to write to.
   * @param data The data to append.
   * @param len The number of bytes to copy.
   * @return The original buffer, for chaining.
   */
  function write(
    buffer memory buf,
    uint256 off,
    bytes memory data,
    uint256 len
  ) internal pure returns (buffer memory) {
    require(len <= data.length);

    if (off + len > buf.capacity) {
      resize(buf, max(buf.capacity, len + off) * 2);
    }

    uint256 dest;
    uint256 src;
    assembly {
      // Memory address of the buffer data
      let bufptr := mload(buf)
      // Length of existing buffer data
      let buflen := mload(bufptr)
      // Start address = buffer address + offset + sizeof(buffer length)
      dest := add(add(bufptr, 32), off)
      // Update buffer length if we're extending it
      if gt(add(len, off), buflen) {
        mstore(bufptr, add(len, off))
      }
      src := add(data, 32)
    }

    // Copy word-length chunks while possible
    for (; len >= 32; len -= 32) {
      assembly {
        mstore(dest, mload(src))
      }
      dest += 32;
      src += 32;
    }

    // Copy remaining bytes
    unchecked {
      uint256 mask = (256**(32 - len)) - 1;
      assembly {
        let srcpart := and(mload(src), not(mask))
        let destpart := and(mload(dest), mask)
        mstore(dest, or(destpart, srcpart))
      }
    }

    return buf;
  }

  /**
   * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @param len The number of bytes to copy.
   * @return The original buffer, for chaining.
   */
  function append(
    buffer memory buf,
    bytes memory data,
    uint256 len
  ) internal pure returns (buffer memory) {
    return write(buf, buf.buf.length, data, len);
  }

  /**
   * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @return The original buffer, for chaining.
   */
  function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
    return write(buf, buf.buf.length, data, data.length);
  }

  /**
   * @dev Writes a byte to the buffer. Resizes if doing so would exceed the
   *      capacity of the buffer.
   * @param buf The buffer to append to.
   * @param off The offset to write the byte at.
   * @param data The data to append.
   * @return The original buffer, for chaining.
   */
  function writeUint8(
    buffer memory buf,
    uint256 off,
    uint8 data
  ) internal pure returns (buffer memory) {
    if (off >= buf.capacity) {
      resize(buf, buf.capacity * 2);
    }

    assembly {
      // Memory address of the buffer data
      let bufptr := mload(buf)
      // Length of existing buffer data
      let buflen := mload(bufptr)
      // Address = buffer address + sizeof(buffer length) + off
      let dest := add(add(bufptr, off), 32)
      mstore8(dest, data)
      // Update buffer length if we extended it
      if eq(off, buflen) {
        mstore(bufptr, add(buflen, 1))
      }
    }
    return buf;
  }

  /**
   * @dev Appends a byte to the buffer. Resizes if doing so would exceed the
   *      capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @return The original buffer, for chaining.
   */
  function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) {
    return writeUint8(buf, buf.buf.length, data);
  }

  /**
   * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would
   *      exceed the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param off The offset to write at.
   * @param data The data to append.
   * @param len The number of bytes to write (left-aligned).
   * @return The original buffer, for chaining.
   */
  function write(
    buffer memory buf,
    uint256 off,
    bytes32 data,
    uint256 len
  ) private pure returns (buffer memory) {
    if (len + off > buf.capacity) {
      resize(buf, (len + off) * 2);
    }

    unchecked {
      uint256 mask = (256**len) - 1;
      // Right-align data
      data = data >> (8 * (32 - len));
      assembly {
        // Memory address of the buffer data
        let bufptr := mload(buf)
        // Address = buffer address + sizeof(buffer length) + off + len
        let dest := add(add(bufptr, off), len)
        mstore(dest, or(and(mload(dest), not(mask)), data))
        // Update buffer length if we extended it
        if gt(add(off, len), mload(bufptr)) {
          mstore(bufptr, add(off, len))
        }
      }
    }
    return buf;
  }

  /**
   * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the
   *      capacity of the buffer.
   * @param buf The buffer to append to.
   * @param off The offset to write at.
   * @param data The data to append.
   * @return The original buffer, for chaining.
   */
  function writeBytes20(
    buffer memory buf,
    uint256 off,
    bytes20 data
  ) internal pure returns (buffer memory) {
    return write(buf, off, bytes32(data), 20);
  }

  /**
   * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @return The original buffer, for chhaining.
   */
  function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
    return write(buf, buf.buf.length, bytes32(data), 20);
  }

  /**
   * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @return The original buffer, for chaining.
   */
  function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
    return write(buf, buf.buf.length, data, 32);
  }

  /**
   * @dev Writes an integer to the buffer. Resizes if doing so would exceed
   *      the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param off The offset to write at.
   * @param data The data to append.
   * @param len The number of bytes to write (right-aligned).
   * @return The original buffer, for chaining.
   */
  function writeInt(
    buffer memory buf,
    uint256 off,
    uint256 data,
    uint256 len
  ) private pure returns (buffer memory) {
    if (len + off > buf.capacity) {
      resize(buf, (len + off) * 2);
    }

    uint256 mask = (256**len) - 1;
    assembly {
      // Memory address of the buffer data
      let bufptr := mload(buf)
      // Address = buffer address + off + sizeof(buffer length) + len
      let dest := add(add(bufptr, off), len)
      mstore(dest, or(and(mload(dest), not(mask)), data))
      // Update buffer length if we extended it
      if gt(add(off, len), mload(bufptr)) {
        mstore(bufptr, add(off, len))
      }
    }
    return buf;
  }

  /**
   * @dev Appends a byte to the end of the buffer. Resizes if doing so would
   * exceed the capacity of the buffer.
   * @param buf The buffer to append to.
   * @param data The data to append.
   * @return The original buffer.
   */
  function appendInt(
    buffer memory buf,
    uint256 data,
    uint256 len
  ) internal pure returns (buffer memory) {
    return writeInt(buf, buf.buf.length, data, len);
  }
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.19;

import {BufferChainlink} from "./BufferChainlink.sol";

library CBORChainlink {
  using BufferChainlink for BufferChainlink.buffer;

  uint8 private constant MAJOR_TYPE_INT = 0;
  uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;
  uint8 private constant MAJOR_TYPE_BYTES = 2;
  uint8 private constant MAJOR_TYPE_STRING = 3;
  uint8 private constant MAJOR_TYPE_ARRAY = 4;
  uint8 private constant MAJOR_TYPE_MAP = 5;
  uint8 private constant MAJOR_TYPE_TAG = 6;
  uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;

  uint8 private constant TAG_TYPE_BIGNUM = 2;
  uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3;

  function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure {
    if(value <= 23) {
      buf.appendUint8(uint8((major << 5) | value));
    } else if (value <= 0xFF) {
      buf.appendUint8(uint8((major << 5) | 24));
      buf.appendInt(value, 1);
    } else if (value <= 0xFFFF) {
      buf.appendUint8(uint8((major << 5) | 25));
      buf.appendInt(value, 2);
    } else if (value <= 0xFFFFFFFF) {
      buf.appendUint8(uint8((major << 5) | 26));
      buf.appendInt(value, 4);
    } else {
      buf.appendUint8(uint8((major << 5) | 27));
      buf.appendInt(value, 8);
    }
  }

  function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure {
    buf.appendUint8(uint8((major << 5) | 31));
  }

  function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure {
    if(value > 0xFFFFFFFFFFFFFFFF) {
      encodeBigNum(buf, value);
    } else {
      encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value));
    }
  }

  function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure {
    if(value < -0x10000000000000000) {
      encodeSignedBigNum(buf, value);
    } else if(value > 0xFFFFFFFFFFFFFFFF) {
      encodeBigNum(buf, uint(value));
    } else if(value >= 0) {
      encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value)));
    } else {
      encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value)));
    }
  }

  function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure {
    encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length));
    buf.append(value);
  }

  function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure {
    buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM));
    encodeBytes(buf, abi.encode(value));
  }

  function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure {
    buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM));
    encodeBytes(buf, abi.encode(uint256(-1 - input)));
  }

  function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure {
    encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length));
    buf.append(bytes(value));
  }

  function startArray(BufferChainlink.buffer memory buf) internal pure {
    encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);
  }

  function startMap(BufferChainlink.buffer memory buf) internal pure {
    encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);
  }

  function endSequence(BufferChainlink.buffer memory buf) internal pure {
    encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);
  }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

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

pragma solidity ^0.8.0;

/**
 * @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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount) external returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Interface for Chainlink feeds
 */
interface IChainlinkFeed {
    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);

    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface for ERC20 tokens
 */
interface IERC20 is IERC20Metadata {
    function burn(address, uint256) external;

    function mint(address, uint256) external;

    function hasRole(bytes32, address) external view returns (bool);
}

File 10 of 51 : IGeneralErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Interface for errors potentially used in all libraries (general names)
 */
interface IGeneralErrors {
    error InitError();
    error InvalidAddresses();
    error InvalidAddress();
    error InvalidInputLength();
    error InvalidCollateralIndex();
    error InvalidAmount();
    error WrongParams();
    error WrongLength();
    error WrongOrder();
    error WrongIndex();
    error BlockOrder();
    error Overflow();
    error ZeroAddress();
    error ZeroValue();
    error AlreadyExists();
    error DoesntExist();
    error Paused();
    error BelowMin();
    error AboveMax();
    error NotAuthorized();
    error WrongTradeType();
    error WrongOrderType();
    error InsufficientBalance();
    error UnsupportedChain();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./types/IAddressStore.sol";
import "./IGeneralErrors.sol";

/**
 * @dev Interface for AddressStoreUtils library
 */
interface IGNSAddressStore is IAddressStore, IGeneralErrors {
    /**
     * @dev Initializes address store facet
     * @param _rolesManager roles manager address
     */
    function initialize(address _rolesManager) external;

    /**
     * @dev Initializes gov emergency timelock role
     * @param _govEmergencyTimelock address to be granted emergency timelock role
     */
    function initializeGovEmergencyTimelock(address _govEmergencyTimelock) external;

    /**
     * @dev Returns addresses current values
     */
    function getAddresses() external view returns (Addresses memory);

    /**
     * @dev Returns whether an account has been granted a particular role
     * @param _account account address to check
     * @param _role role to check
     */
    function hasRole(address _account, Role _role) external view returns (bool);

    /**
     * @dev Returns whether an account has been granted at least one of two roles
     * @param _account address to check
     * @param _roleA first role to check
     * @param _roleB second role to check
     */
    function hasRoles(address _account, Role _roleA, Role _roleB) external view returns (bool);

    /**
     * @dev Updates access control for a list of accounts
     * @param _accounts accounts addresses to update
     * @param _roles corresponding roles to update
     * @param _values corresponding new values to set
     */
    function setRoles(address[] calldata _accounts, Role[] calldata _roles, bool[] calldata _values) external;

    /**
     * @dev Emitted when addresses are updated
     * @param addresses new addresses values
     */
    event AddressesUpdated(Addresses addresses);

    /**
     * @dev Emitted when access control is updated for an account
     * @param target account address to update
     * @param role role to update
     * @param access whether role is granted or revoked
     */
    event AccessControlUpdated(address target, Role role, bool access);

    error NotAllowed();
    error WrongAccess();
}

File 12 of 51 : IGNSDiamond.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./IGNSAddressStore.sol";
import "./IGNSDiamondCut.sol";
import "./IGNSDiamondLoupe.sol";
import "./types/ITypes.sol";

/**
 * @dev the non-expanded interface for multi-collat diamond, only contains types/structs/enums
 */

interface IGNSDiamond is IGNSAddressStore, IGNSDiamondCut, IGNSDiamondLoupe, ITypes {

}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./types/IDiamondStorage.sol";

/**
 * @author Nick Mudge <[email protected]> (https://twitter.com/mudgen)
 * @author Gains Network
 * @dev Based on EIP-2535: Diamonds (https://eips.ethereum.org/EIPS/eip-2535)
 * @dev Follows diamond-3 implementation (https://github.com/mudgen/diamond-3-hardhat/)
 * @dev One of the diamond standard interfaces, used for diamond management.
 */
interface IGNSDiamondCut is IDiamondStorage {
    /**
     * @notice Add/replace/remove any number of functions and optionally execute a function with delegatecall
     * @param _diamondCut Contains the facet addresses and function selectors
     * @param _init The address of the contract or facet to execute _calldata
     * @param _calldata A function call, including function selector and arguments _calldata is executed with delegatecall on _init
     */
    function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;

    /**
     * @dev Emitted when function selectors of a facet of the diamond is added, replaced, or removed
     * @param _diamondCut Contains the update data (facet addresses, action, function selectors)
     * @param _init The address of the contract or facet to execute _calldata
     * @param _calldata Function call to execute after the diamond cut
     */
    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);

    error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);
    error InvalidFacetCutAction();
    error NotContract();
    error NotFound();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @author Nick Mudge <[email protected]> (https://twitter.com/mudgen)
 * @author Gains Network
 * @dev Based on EIP-2535: Diamonds (https://eips.ethereum.org/EIPS/eip-2535)
 * @dev Follows diamond-3 implementation (https://github.com/mudgen/diamond-3-hardhat/)
 * @dev One of the diamond standard interfaces, used to inspect the diamond like a magnifying glass.
 */
interface IGNSDiamondLoupe {
    /// These functions are expected to be called frequently
    /// by tools.

    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /// @notice Gets all facet addresses and their four byte function selectors.
    /// @return facets_ Facet
    function facets() external view returns (Facet[] memory facets_);

    /// @notice Gets all the function selectors supported by a specific facet.
    /// @param _facet The facet address.
    /// @return facetFunctionSelectors_
    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /// @notice Get all the facet addresses used by a diamond.
    /// @return facetAddresses_
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /// @notice Gets the facet that supports the given selector.
    /// @dev If facet is not found return address(0).
    /// @param _functionSelector The function selector.
    /// @return facetAddress_ The facet address.
    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}

File 15 of 51 : IGNSMultiCollatDiamond.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./IGNSDiamond.sol";
import "./libraries/IPairsStorageUtils.sol";
import "./libraries/IReferralsUtils.sol";
import "./libraries/IFeeTiersUtils.sol";
import "./libraries/IPriceImpactUtils.sol";
import "./libraries/ITradingStorageUtils.sol";
import "./libraries/ITriggerRewardsUtils.sol";
import "./libraries/ITradingInteractionsUtils.sol";
import "./libraries/ITradingCallbacksUtils.sol";
import "./libraries/IBorrowingFeesUtils.sol";
import "./libraries/IPriceAggregatorUtils.sol";
import "./libraries/IOtcUtils.sol";
import "./IMulticall.sol";
import "./libraries/IChainConfigUtils.sol";
import "./libraries/IFundingFeesUtils.sol";

/**
 * @dev Expanded version of multi-collat diamond that includes events and function signatures
 * Technically this interface is virtual since the diamond doesn't directly implement these functions.
 * It only forwards the calls to the facet contracts using delegatecall.
 */
interface IGNSMultiCollatDiamond is
    IGNSDiamond,
    IPairsStorageUtils,
    IReferralsUtils,
    IFeeTiersUtils,
    IPriceImpactUtils,
    ITradingStorageUtils,
    ITriggerRewardsUtils,
    ITradingInteractionsUtils,
    ITradingCallbacksUtils,
    IBorrowingFeesUtils,
    IPriceAggregatorUtils,
    IOtcUtils,
    IMulticall,
    IChainConfigUtils,
    IFundingFeesUtils
{}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @custom:version 8
 * @dev Generic interface for liquidity pool methods for fetching observations (to calculate TWAP) and other basic information
 */
interface ILiquidityPool {
    /**
     * @dev AlgebraPool V1.9 equivalent of Uniswap V3 `observe` function
     * See https://github.com/cryptoalgebra/AlgebraV1.9/blob/main/src/core/contracts/interfaces/pool/IAlgebraPoolDerivedState.sol for more information
     */
    function getTimepoints(
        uint32[] calldata secondsAgos
    )
        external
        view
        returns (
            int56[] memory tickCumulatives,
            uint160[] memory secondsPerLiquidityCumulatives,
            uint112[] memory volatilityCumulatives,
            uint256[] memory volumePerAvgLiquiditys
        );

    /**
     * @dev Uniswap V3 `observe` function
     * See `https://github.com/Uniswap/v3-core/blob/main/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol` for more information
     */
    function observe(
        uint32[] calldata secondsAgos
    ) external view returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);

    /**
     * @notice The first of the two tokens of the pool, sorted by address
     * @return The token contract address
     */
    function token0() external view returns (address);

    /**
     * @notice The second of the two tokens of the pool, sorted by address
     * @return The token contract address
     */
    function token1() external view returns (address);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IMulticall {
    /**
     * @dev Call multiple functions in a single call.
     * @param data The data for the calls.
     * @return results The results of the calls.
     */
    function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}

File 18 of 51 : IBorrowingFeesUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IFundingFees.sol";
import "../types/IPriceAggregator.sol";
import "../types/IBorrowingFees.sol";

/**
 * @dev Interface for GNSBorrowingFees facet (inherits types and also contains functions, events, and custom errors)
 */
interface IBorrowingFeesUtils is IBorrowingFees {
    /**
     * @dev Initializes default fee per block caps
     * @param _feePerBlockCap the new cap values
     */
    function initializeBorrowingFeePerBlockCap(BorrowingFeePerBlockCap memory _feePerBlockCap) external;

    /**
     * @dev Updates borrowing pair params of a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _value new value
     * @param _signedPairPrices signed pair market prices
     */
    function setBorrowingPairParams(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        BorrowingPairParams calldata _value,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates borrowing pair params of multiple pairs
     * @param _collateralIndex index of the collateral
     * @param _indices indices of the pairs
     * @param _values new values
     * @param _signedPairPrices signed pair market prices
     */
    function setBorrowingPairParamsArray(
        uint8 _collateralIndex,
        uint16[] calldata _indices,
        BorrowingPairParams[] calldata _values,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates borrowing group params of a group
     * @param _collateralIndex index of the collateral
     * @param _groupIndex index of the borrowing group
     * @param _value new value
     */
    function setBorrowingGroupParams(
        uint8 _collateralIndex,
        uint16 _groupIndex,
        BorrowingGroupParams calldata _value
    ) external;

    /**
     * @dev Updates borrowing group params of multiple groups
     * @param _collateralIndex index of the collateral
     * @param _indices indices of the groups
     * @param _values new values
     */
    function setBorrowingGroupParamsArray(
        uint8 _collateralIndex,
        uint16[] calldata _indices,
        BorrowingGroupParams[] calldata _values
    ) external;

    /**
     * @dev Updates default borrowing fee per block caps
     * @param _feePerBlockCap new value
     */
    function setBorrowingFeePerBlockCap(IBorrowingFees.BorrowingFeePerBlockCap memory _feePerBlockCap) external;

    /**
     * @dev Updates borrowing fee per block caps for multiple pairs
     * @param _collateralIndex index of the collateral
     * @param _indices indices of the pairs
     * @param _values new values
     */
    function setBorrowingPairFeePerBlockCapArray(
        uint8 _collateralIndex,
        uint16[] calldata _indices,
        IBorrowingFees.BorrowingFeePerBlockCap[] calldata _values
    ) external;

    /**
     * @dev Callback for borrowing param update
     * @param _paramUpdate param update details
     * @param _currentPairPrice current pair price (1e10)
     */
    function borrowingParamUpdateCallback(
        IFundingFees.PendingParamUpdate memory _paramUpdate,
        uint256 _currentPairPrice
    ) external;

    /**
     * @dev Callback after a trade is opened/closed to store pending borrowing fees and update group OI
     * @param _collateralIndex index of the collateral
     * @param _trader address of the trader
     * @param _pairIndex index of the pair
     * @param _index index of the trade
     * @param _positionSizeCollateral position size of the trade in collateral tokens
     * @param _open true if trade has been opened, false if trade has been closed
     * @param _long true if trade is long, false if trade is short
     * @param _currentPairPrice current pair price (1e10)
     */
    function handleTradeBorrowingCallback(
        uint8 _collateralIndex,
        address _trader,
        uint16 _pairIndex,
        uint32 _index,
        uint256 _positionSizeCollateral,
        bool _open,
        bool _long,
        uint256 _currentPairPrice
    ) external;

    /**
     * @dev Updates a pair's open interest (before v10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _long true if long side
     * @param _increase true if open interest is increased, false if decreased
     * @param _amountCollateral change in open interest in collateral tokens (collateral precision)
     */
    function updatePairOiBeforeV10(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        bool _long,
        bool _increase,
        uint256 _amountCollateral
    ) external;

    /**
     * @dev Returns the pending acc borrowing fees for a pair on both sides
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _currentBlock current block number
     * @param _currentPairPrice current pair price (1e10)
     * @return accFeeLong new pair acc borrowing fee on long side
     * @return accFeeShort new pair acc borrowing fee on short side
     * @return pairAccFeeLongDelta  pair acc borrowing fee delta on long side
     * @return pairAccFeeShortDelta  pair acc borrowing fee delta on short side
     */
    function getBorrowingPairPendingAccFees(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        uint256 _currentBlock,
        uint256 _currentPairPrice
    )
        external
        view
        returns (uint64 accFeeLong, uint64 accFeeShort, uint64 pairAccFeeLongDelta, uint64 pairAccFeeShortDelta);

    /**
     * @dev Returns the pending acc borrowing fees for a borrowing group on both sides
     * @param _collateralIndex index of the collateral
     * @param _groupIndex index of the borrowing group
     * @param _currentBlock current block number
     * @return accFeeLong new group acc borrowing fee on long side
     * @return accFeeShort new group acc borrowing fee on short side
     * @return groupAccFeeLongDelta  group acc borrowing fee delta on long side
     * @return groupAccFeeShortDelta  group acc borrowing fee delta on short side
     */
    function getBorrowingGroupPendingAccFees(
        uint8 _collateralIndex,
        uint16 _groupIndex,
        uint256 _currentBlock
    )
        external
        view
        returns (uint64 accFeeLong, uint64 accFeeShort, uint64 groupAccFeeLongDelta, uint64 groupAccFeeShortDelta);

    /**
     * @dev Returns the borrowing fee for a trade
     * @param _input input data (collateralIndex, trader, pairIndex, index, long, collateral, leverage)
     * @return feeAmountCollateral borrowing fee (collateral precision)
     */
    function getTradeBorrowingFee(BorrowingFeeInput memory _input) external view returns (uint256 feeAmountCollateral);

    /**
     * @dev Returns the liquidation price for a trade
     * @param _input input data (collateralIndex, trader, pairIndex, index, openPrice, long, collateral, leverage)
     */
    function getTradeLiquidationPrice(LiqPriceInput calldata _input) external view returns (uint256);

    /**
     * @dev Returns the open interests for a pair (before v10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @return longOi open interest on long side
     * @return shortOi open interest on short side
     */
    function getPairOisBeforeV10Collateral(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (uint256 longOi, uint256 shortOi);

    /**
     * @dev Returns the borrowing group index for a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @return groupIndex borrowing group index
     */
    function getBorrowingPairGroupIndex(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (uint16 groupIndex);

    /**
     * @dev Returns the open interest in collateral tokens for a pair on one side (before v10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _long true if long side
     */
    function getPairOiBeforeV10Collateral(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        bool _long
    ) external view returns (uint256);

    /**
     * @dev Returns whether a trade is within the max group borrowing open interest
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _long true if long side
     * @param _positionSizeCollateral position size of the trade in collateral tokens
     */
    function withinMaxBorrowingGroupOi(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        bool _long,
        uint256 _positionSizeCollateral
    ) external view returns (bool);

    /**
     * @dev Returns a borrowing group's data
     * @param _collateralIndex index of the collateral
     * @param _groupIndex index of the borrowing group
     */
    function getBorrowingGroup(
        uint8 _collateralIndex,
        uint16 _groupIndex
    ) external view returns (BorrowingData memory group);

    /**
     * @dev Returns a borrowing group's oi data
     * @param _collateralIndex index of the collateral
     * @param _groupIndex index of the borrowing group
     */
    function getBorrowingGroupOi(
        uint8 _collateralIndex,
        uint16 _groupIndex
    ) external view returns (OpenInterest memory group);

    /**
     * @dev Returns a borrowing pair's data
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getBorrowingPair(uint8 _collateralIndex, uint16 _pairIndex) external view returns (BorrowingData memory);

    /**
     * @dev Returns a borrowing pair's oi data (before v10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getBorrowingPairOiBeforeV10(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (OpenInterest memory);

    /**
     * @dev Returns a borrowing pair's oi data
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getBorrowingPairGroups(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (BorrowingPairGroup[] memory);

    /**
     * @dev Returns all borrowing pairs' borrowing data, oi data, and pair groups data
     * @param _collateralIndex index of the collateral
     */
    function getAllBorrowingPairs(
        uint8 _collateralIndex
    ) external view returns (BorrowingData[] memory, OpenInterest[] memory, BorrowingPairGroup[][] memory);

    /**
     * @dev Returns borrowing groups' data and oi data
     * @param _collateralIndex index of the collateral
     * @param _indices indices of the groups
     */
    function getBorrowingGroups(
        uint8 _collateralIndex,
        uint16[] calldata _indices
    ) external view returns (BorrowingData[] memory, OpenInterest[] memory);

    /**
     * @dev Returns borrowing groups' data
     * @param _collateralIndex index of the collateral
     * @param _trader address of trader
     * @param _index index of trade
     */
    function getBorrowingInitialAccFees(
        uint8 _collateralIndex,
        address _trader,
        uint32 _index
    ) external view returns (BorrowingInitialAccFees memory);

    /**
     * @dev Returns the max open interest for a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairMaxOi(uint8 _collateralIndex, uint16 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns the max open interest in collateral tokens for a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairMaxOiCollateral(uint8 _collateralIndex, uint16 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns the default minimum and maximum fee per block percentage (1e3 precision)
     */
    function getBorrowingFeePerBlockCap() external view returns (BorrowingFeePerBlockCap memory);

    /**
     * @dev Returns the minimum and maximum fee per block percentage for a pair (1e3 precision)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getBorrowingPairFeePerBlockCap(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (BorrowingFeePerBlockCap memory);

    /**
     * @dev Returns the minimum and maximum fee per block percentage for multiple pairs
     * @param _collateralIndex index of the collateral
     * @param _indices indices of the pairs
     */
    function getBorrowingPairFeePerBlockCaps(
        uint8 _collateralIndex,
        uint16[] calldata _indices
    ) external view returns (BorrowingFeePerBlockCap[] memory);

    /**
     * @dev Emitted when a pair's borrowing params is updated
     * @param pairIndex index of the pair
     * @param groupIndex index of its new group
     * @param feePerBlock new fee per block
     * @param feeExponent new fee exponent
     * @param maxOi new max open interest
     */
    event BorrowingPairParamsUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint16 indexed groupIndex,
        uint32 feePerBlock,
        uint48 feeExponent,
        uint72 maxOi
    );

    /**
     * @dev Emitted when a pair's borrowing group has been updated
     * @param pairIndex index of the pair
     * @param prevGroupIndex previous borrowing group index
     * @param newGroupIndex new borrowing group index
     */
    event BorrowingPairGroupUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint16 prevGroupIndex,
        uint16 newGroupIndex
    );

    /**
     * @dev Emitted when a group's borrowing params is updated
     * @param groupIndex index of the group
     * @param feePerBlock new fee per block
     * @param maxOi new max open interest
     * @param feeExponent new fee exponent
     */
    event BorrowingGroupUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed groupIndex,
        uint32 feePerBlock,
        uint72 maxOi,
        uint48 feeExponent
    );

    /**
     * @dev Emitted when a trade's initial acc borrowing fees are stored
     * @param collateralIndex index of collateral
     * @param trader address of the trader
     * @param pairIndex index of the pair
     * @param index index of the trade
     * @param long true if trade is long, false if trade is short
     * @param currentPairPrice current pair price (1e10)
     * @param initialPairAccFee initial pair acc fee (for the side of the trade)
     * @param initialGroupAccFee initial group acc fee (for the side of the trade)
     */
    event BorrowingInitialAccFeesStored(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint16 indexed pairIndex,
        uint32 index,
        bool long,
        uint256 currentPairPrice,
        uint64 initialPairAccFee,
        uint64 initialGroupAccFee
    );

    /**
     * @dev Emitted when a trade is executed and borrowing callback is handled
     * @param trader address of the trader
     * @param pairIndex index of the pair
     * @param index index of the trade
     * @param open true if trade has been opened, false if trade has been closed
     * @param long true if trade is long, false if trade is short
     * @param currentPairPrice current pair price (1e10)
     * @param positionSizeCollateral position size of the trade in collateral tokens
     */
    event TradeBorrowingCallbackHandled(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint16 indexed pairIndex,
        uint32 index,
        bool open,
        bool long,
        uint256 currentPairPrice,
        uint256 positionSizeCollateral
    );

    /**
     * @dev Emitted when a pair's borrowing acc fees are updated
     * @param pairIndex index of the pair
     * @param currentBlock current block number
     * @param currentPairPrice current pair price (1e10)
     * @param accFeeLong new pair acc borrowing fee on long side
     * @param accFeeShort new pair acc borrowing fee on short side
     */
    event BorrowingPairAccFeesUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint256 currentBlock,
        uint256 currentPairPrice,
        uint64 accFeeLong,
        uint64 accFeeShort
    );

    /**
     * @dev Emitted when a group's borrowing acc fees are updated
     * @param groupIndex index of the borrowing group
     * @param currentBlock current block number
     * @param accFeeLong new group acc borrowing fee on long side
     * @param accFeeShort new group acc borrowing fee on short side
     */
    event BorrowingGroupAccFeesUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed groupIndex,
        uint256 currentBlock,
        uint64 accFeeLong,
        uint64 accFeeShort
    );

    /**
     * @dev Emitted when a borrowing pair's open interests are updated
     * @param pairIndex index of the pair
     * @param long true if long side
     * @param increase true if open interest is increased, false if decreased
     * @param delta change in open interest in collateral tokens (1e10 precision)
     * @param newOiLong new open interest on long side
     * @param newOiShort new open interest on short side
     */
    event BorrowingPairOiBeforeV10Updated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        bool long,
        bool increase,
        uint72 delta,
        uint72 newOiLong,
        uint72 newOiShort
    );

    /**
     * @dev Emitted when a borrowing group's open interests are updated
     * @param groupIndex index of the borrowing group
     * @param long true if long side
     * @param increase true if open interest is increased, false if decreased
     * @param delta change in open interest in collateral tokens (1e10 precision)
     * @param newOiLong new open interest on long side
     * @param newOiShort new open interest on short side
     */
    event BorrowingGroupOiUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed groupIndex,
        bool long,
        bool increase,
        uint72 delta,
        uint72 newOiLong,
        uint72 newOiShort
    );

    /**
     * @dev Emitted when the default fee per block cap is updated
     * @param minP new min value (1e3% precision)
     * @param maxP new max value (1e3% precision)
     */
    event BorrowingFeePerBlockCapUpdated(uint32 minP, uint32 maxP);

    /**
     * @dev Emitted when the a pair's fee per block cap is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param minP new min value (1e3% precision)
     * @param maxP new max value (1e3% precision)
     */
    event BorrowingPairFeePerBlockCapUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint32 minP,
        uint32 maxP
    );

    error BorrowingZeroGroup();
    error BorrowingWrongExponent();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IChainConfig.sol";

/**
 * @dev Interface for GNSChainConfig facet (inherits types and also contains functions, events, and custom errors)
 */
interface IChainConfigUtils is IChainConfig {
    /**
     * @dev Initializer for ChainConfig facet
     * @param _nativeTransferGasLimit new native transfer gas limit
     * @param _nativeTransferEnabled whether native transfers should be enabled
     */
    function initializeChainConfig(uint16 _nativeTransferGasLimit, bool _nativeTransferEnabled) external;

    /**
     * @dev Updates native transfer gas limit
     * @param _nativeTransferGasLimit new native transfer gas limit. Must be greater or equal to MIN_NATIVE_TRANSFER_GAS_LIMIT.
     */
    function updateNativeTransferGasLimit(uint16 _nativeTransferGasLimit) external;

    /**
     * @dev Updates `nativeTransferEnabled`. When true, the diamond is allowed to unwrap native tokens on transfer-out.
     * @param _nativeTransferEnable the new value
     */
    function updateNativeTransferEnabled(bool _nativeTransferEnable) external;

    /**
     * @dev Returns gas limit to be used for native transfers, with a minimum of `MIN_NATIVE_TRANSFER_GAS_LIMIT` (21k gas)
     */
    function getNativeTransferGasLimit() external returns (uint16);

    /**
     * @dev Returns whether native transfers are enabled
     */
    function getNativeTransferEnabled() external returns (bool);

    /**
     * @dev Returns the current value for reentrancy lock
     */
    function getReentrancyLock() external returns (uint256);

    /**
     * @dev Emitted when `nativeTransferGasLimit` is updated
     * @param newLimit new gas limit
     */
    event NativeTransferGasLimitUpdated(uint16 newLimit);

    /**
     * @dev Emitted when `nativeTransferEnabled` is updated
     * @param enabled the new value
     */
    event NativeTransferEnabledUpdated(bool enabled);
}

File 20 of 51 : IFeeTiersUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IFeeTiers.sol";

/**
 * @dev Interface for GNSFeeTiers facet (inherits types and also contains functions, events, and custom errors)
 */
interface IFeeTiersUtils is IFeeTiers {
    /**
     *
     * @param _groupIndices group indices (pairs storage fee index) to initialize
     * @param _groupVolumeMultipliers corresponding group volume multipliers (1e3)
     * @param _feeTiersIndices fee tiers indices to initialize
     * @param _feeTiers fee tiers values to initialize (feeMultiplier, pointsThreshold)
     */
    function initializeFeeTiers(
        uint256[] calldata _groupIndices,
        uint256[] calldata _groupVolumeMultipliers,
        uint256[] calldata _feeTiersIndices,
        IFeeTiersUtils.FeeTier[] calldata _feeTiers
    ) external;

    /**
     * @dev Updates groups volume multipliers
     * @param _groupIndices indices of groups to update
     * @param _groupVolumeMultipliers corresponding new volume multipliers (1e3)
     */
    function setGroupVolumeMultipliers(
        uint256[] calldata _groupIndices,
        uint256[] calldata _groupVolumeMultipliers
    ) external;

    /**
     * @dev Updates fee tiers
     * @param _feeTiersIndices indices of fee tiers to update
     * @param _feeTiers new fee tiers values (feeMultiplier, pointsThreshold)
     */
    function setFeeTiers(uint256[] calldata _feeTiersIndices, IFeeTiersUtils.FeeTier[] calldata _feeTiers) external;

    /**
     * @dev Updates traders enrollment status in fee tiers program, including staking tier discounts
     * @param _traders group of traders
     * @param _values corresponding enrollment values
     */
    function setTradersFeeTiersEnrollment(
        address[] calldata _traders,
        IFeeTiersUtils.TraderEnrollment[] calldata _values
    ) external;

    /**
     * @dev Credits points to traders
     * @param _traders traders addresses
     * @param _creditTypes types of credit (IMMEDIATE, CLAIMABLE)
     * @param _points points to credit (1e18)
     */
    function addTradersUnclaimedPoints(
        address[] calldata _traders,
        IFeeTiersUtils.CreditType[] calldata _creditTypes,
        uint224[] calldata _points
    ) external;

    /**
     * @dev Increases daily points from a new trade, re-calculate trailing points, and cache daily fee tier for a trader.
     * @param _trader trader address
     * @param _volumeUsd trading volume in USD (1e18)
     * @param _pairIndex pair index
     */
    function updateTraderPoints(address _trader, uint256 _volumeUsd, uint256 _pairIndex) external;

    /**
     * @dev Returns fee amount after applying the trader's active fee tier and staking tier multiplier
     * @param _trader address of trader
     * @param _normalFeeAmountCollateral base fee amount (collateral precision)
     */
    function calculateFeeAmount(address _trader, uint256 _normalFeeAmountCollateral) external view returns (uint256);

    /**
     * Returns the current number of active fee tiers
     */
    function getFeeTiersCount() external view returns (uint256);

    /**
     * @dev Returns a fee tier's details (feeMultiplier, pointsThreshold)
     * @param _feeTierIndex fee tier index
     */
    function getFeeTier(uint256 _feeTierIndex) external view returns (IFeeTiersUtils.FeeTier memory);

    /**
     * @dev Returns fee tier details (feeMultiplier, pointsThreshold) for all active tiers
     */
    function getFeeTiers() external view returns (IFeeTiers.FeeTier[] memory);

    /**
     * @dev Returns a group's volume multiplier
     * @param _groupIndex group index (pairs storage fee index)
     */
    function getGroupVolumeMultiplier(uint256 _groupIndex) external view returns (uint256);

    /**
     * @dev Returns a list of group volume multipliers
     * @param _groupIndices group indices
     */
    function getGroupVolumeMultipliers(uint256[] calldata _groupIndices) external view returns (uint256[] memory);

    /**
     * @dev Returns a trader's info (lastDayUpdated, trailingPoints)
     * @param _trader trader address
     */
    function getFeeTiersTraderInfo(address _trader) external view returns (IFeeTiersUtils.TraderInfo memory);

    /**
     * @dev Returns a trader's daily fee tier info (feeMultiplierCache, points)
     * @param _trader trader address
     * @param _day day
     */
    function getFeeTiersTraderDailyInfo(
        address _trader,
        uint32 _day
    ) external view returns (IFeeTiersUtils.TraderDailyInfo memory);

    /**
     * @dev Returns a trader's fee tiers enrollment status
     * @param _trader trader address
     */
    function getTraderFeeTiersEnrollment(
        address _trader
    ) external view returns (IFeeTiersUtils.TraderEnrollment memory);

    /**
     * @dev Returns a trader's unclaimed points, credited by Governance
     * @param _trader trader address
     */
    function getTraderUnclaimedPoints(address _trader) external view returns (uint224);

    /**
     * @dev Initializes GNS staking with tier configuration
     * @param _tierIndices tier indices to initialize
     * @param _tiers tier configurations (discountP, gnsThreshold)
     * @param _gnsVaultAddress address for gGNS or another ERC4626 GNS vault
     * @param _useGnsVaultBalance if true, gnsVaultAddress balance is used for tier calculation
     */
    function initializeGnsStakingTiers(
        uint256[] calldata _tierIndices,
        IFeeTiers.FeeTier[] calldata _tiers,
        address _gnsVaultAddress,
        bool _useGnsVaultBalance
    ) external;

    /**
     * @dev Updates GNS staking tiers
     * @param _tierIndices indices of tiers to update
     * @param _tiers new tier configurations (discountP, gnsThreshold)
     */
    function setGnsStakingTiers(uint256[] calldata _tierIndices, IFeeTiers.FeeTier[] calldata _tiers) external;

    /**
     * @dev Updated whether to use gGNS balance for tier calculation
     * @param _useGnsVaultBalance new value
     */
    function setUseGnsVaultBalance(bool _useGnsVaultBalance) external;

    /**
     * @dev Sets bonus GNS amounts for traders. Counts towards staking tier calculation, but is not withdrawable.
     * @param _traders trader addresses
     * @param _bonusAmounts bonus GNS amounts (no precision)
     */
    function setGnsStakingBonusAmounts(address[] calldata _traders, uint24[] calldata _bonusAmounts) external;

    /**
     * @dev Syncs cached discount tiers for traders based on current tier configuration. Used to force a tier refresh in case of tier updates or gGNS repricing.
     * @param _traders trader addresses to sync
     */
    function syncGnsStakingTiers(address[] calldata _traders) external;

    /**
     * @dev Stakes GNS tokens for fee discounts
     * @param _amountGns GNS amount to stake (1e18)
     * @param _amountVaultGns gGNS amount to stake (1e18)
     */
    function stakeGns(uint88 _amountGns, uint88 _amountVaultGns) external;

    /**
     * @dev Unstakes GNS tokens
     * @param _amountGns GNS amount to unstake (1e18)
     * @param _amountVaultGns gGNS amount to unstake (1e18)
     */
    function unstakeGns(uint88 _amountGns, uint88 _amountVaultGns) external;

    /**
     * Returns the current number of active staking tiers
     */
    function getGnsStakingTiersCount() external view returns (uint256);

    /**
     * @dev Returns GNS staking tier configuration
     * @param _tierIndex tier index
     */
    function getGnsStakingTier(uint256 _tierIndex) external view returns (IFeeTiers.FeeTier memory);

    /**
     * @dev Returns GNS staking tier configuration for all active tiers
     */
    function getGnsStakingTiers() external view returns (IFeeTiers.FeeTier[] memory);

    /**
     * @dev Returns GNS vault address used for staking tiers
     */
    function getGnsVaultAddress() external view returns (address);

    /**
     * @dev Returns whether gGNS balance is used for tier calculation
     */
    function getUseGnsVaultBalance() external view returns (bool);

    /**
     * @dev Returns trader's GNS staking information
     * @param _trader trader address
     */
    function getGnsStakingInfo(address _trader) external view returns (IFeeTiers.GnsStakingInfo memory);

    /**
     * @dev Returns multiple traders' GNS staking information
     * @param _traders trader addresses
     */
    function getGnsStakingInfos(address[] calldata _traders) external view returns (IFeeTiers.GnsStakingInfo[] memory);

    /**
     * @dev Returns the GNS value of staked gGNS amount, based on the vault's current price per share. Returns 0 when `useGnsVaultBalance` is false
     * @param _stakedVaultGns staked gGNS amount (1e18)
     */
    function getStakedVaultGnsValue(uint88 _stakedVaultGns) external view returns (uint256);

    /**
     * @dev Emitted when group volume multipliers are updated
     * @param groupIndices indices of updated groups
     * @param groupVolumeMultipliers new corresponding volume multipliers (1e3)
     */
    event GroupVolumeMultipliersUpdated(uint256[] groupIndices, uint256[] groupVolumeMultipliers);

    /**
     * @dev Emitted when fee tiers are updated
     * @param feeTiersIndices indices of updated fee tiers
     * @param feeTiers new corresponding fee tiers values (feeMultiplier, pointsThreshold)
     */
    event FeeTiersUpdated(uint256[] feeTiersIndices, IFeeTiersUtils.FeeTier[] feeTiers);

    /**
     * @dev Emitted when a trader's daily points are updated
     * @param trader trader address
     * @param day day
     * @param points points added (1e18 precision)
     */
    event TraderDailyPointsIncreased(address indexed trader, uint32 indexed day, uint224 points);

    /**
     * @dev Emitted when a trader info is updated for the first time
     * @param trader address of trader
     * @param day day
     */
    event TraderInfoFirstUpdate(address indexed trader, uint32 day);

    /**
     * @dev Emitted when a trader's trailing points are updated
     * @param trader trader address
     * @param fromDay from day
     * @param toDay to day
     * @param expiredPoints expired points amount (1e18 precision)
     */
    event TraderTrailingPointsExpired(address indexed trader, uint32 fromDay, uint32 toDay, uint224 expiredPoints);

    /**
     * @dev Emitted when a trader's info is updated
     * @param trader address of trader
     * @param traderInfo new trader info value (lastDayUpdated, trailingPoints)
     */
    event TraderInfoUpdated(address indexed trader, IFeeTiersUtils.TraderInfo traderInfo);

    /**
     * @dev Emitted when a trader's cached fee multiplier is updated (this is the one used in fee calculations)
     * @param trader address of trader
     * @param day day
     * @param feeMultiplier new fee multiplier (1e3 precision)
     */
    event TraderFeeMultiplierCached(address indexed trader, uint32 indexed day, uint32 feeMultiplier);

    /**
     * @dev Emitted when a trader's enrollment status is updated
     * @param trader address of trader
     * @param enrollment trader's new enrollment status
     */
    event TraderEnrollmentUpdated(address indexed trader, IFeeTiersUtils.TraderEnrollment enrollment);

    /**
     * @dev Emitted when a trader is credited points by governance
     * @param trader trader address
     * @param day day the points were credited on, may be different from the day the points were claimed
     * @param creditType credit type (IMMEDIATE, CLAIMABLE)
     * @param points points added (1e18 precision)
     */
    event TraderPointsCredited(
        address indexed trader,
        uint32 indexed day,
        IFeeTiers.CreditType creditType,
        uint224 points
    );

    /**
     * @dev Emitted when a trader's unclaimed points are claimed
     * @param trader trader address
     * @param day day of claim
     * @param points points added (1e18 precision)
     */
    event TraderUnclaimedPointsClaimed(address indexed trader, uint32 indexed day, uint224 points);

    /**
     * @dev Emitted when GNS staking tiers are updated
     * @param indices tier indices updated
     * @param tiers new tier configurations
     */
    event GnsStakingTiersUpdated(uint256[] indices, IFeeTiers.FeeTier[] tiers);

    /**
     * @dev Emitted when the use of GNS vault balance for tier calculation is updated
     * @param newValue new value
     */
    event UseGnsVaultBalanceUpdated(bool newValue);

    /**
     * @dev Emitted when a trader stakes GNS tokens
     * @param trader trader address
     * @param amountGns GNS amount staked (1e18)
     * @param amountVaultGns gGNS amount staked (1e18)
     */
    event GnsStaked(address indexed trader, uint88 amountGns, uint88 amountVaultGns);

    /**
     * @dev Emitted when a trader unstakes GNS tokens
     * @param trader trader address
     * @param amountGns GNS amount unstaked (1e18)
     * @param amountVaultGns gGNS amount unstaked (1e18)
     */
    event GnsUnstaked(address indexed trader, uint88 amountGns, uint88 amountVaultGns);

    /**
     * @dev Emitted when a trader's gns staking fee multiplier is updated (used in fee calculations, in conjunction with volume fee tiers multiplier)
     * @param feeMultiplier new fee multiplier (1e3 precision)
     */
    event GnsStakingFeeMultiplierCached(address indexed trader, uint32 feeMultiplier);

    /**
     * @dev Emitted when traders' bonus GNS amount is updated
     * @param traders trader addresses
     * @param bonusAmounts bonus amounts (no precision)
     */
    event GnsStakingBonusUpdated(address[] traders, uint24[] bonusAmounts);

    error WrongFeeTier();
    error PointsOverflow();
    error StakingCooldownActive();
}

File 21 of 51 : IFundingFeesUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IFundingFees.sol";
import "../types/IPriceAggregator.sol";
import "../types/ITradingCallbacks.sol";

/**
 * @dev Interface for GNSFundingFees facet (inherits types and also contains functions, events, and custom errors)
 */
interface IFundingFeesUtils is IFundingFees {
    /**
     * @dev Updates max skew in collateral tokens for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _maxSkewCollateral new value (1e10)
     */
    function setMaxSkewCollateral(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint80[] calldata _maxSkewCollateral
    ) external;

    /**
     * @dev Updates funding skew coefficient per year for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _skewCoefficientPerYear new value (1e26)
     * @param _signedPairPrices signed pair market prices
     */
    function setSkewCoefficientPerYear(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint112[] calldata _skewCoefficientPerYear,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates absolute funding velocity per year cap for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _absoluteVelocityPerYearCap new value (1e7)
     * @param _signedPairPrices signed pair market prices
     */
    function setAbsoluteVelocityPerYearCap(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint24[] calldata _absoluteVelocityPerYearCap,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates funding rate % per second absolute cap for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _absoluteRatePerSecondCap new value (1e10)
     * @param _signedPairPrices signed pair market prices
     */
    function setAbsoluteRatePerSecondCap(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint24[] calldata _absoluteRatePerSecondCap,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates funding theta threshold for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _thetaThresholdUsd new value (USD)
     * @param _signedPairPrices signed pair market prices
     */
    function setThetaThresholdUsd(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint32[] calldata _thetaThresholdUsd,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Enables/disables funding fees for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _fundingFeesEnabled new value
     * @param _signedPairPrices signed pair market prices
     */
    function setFundingFeesEnabled(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        bool[] calldata _fundingFeesEnabled,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Enables/disables APR multiplier for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _aprMultiplierEnabled new value
     * @param _signedPairPrices signed pair market prices
     */
    function setAprMultiplierEnabled(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        bool[] calldata _aprMultiplierEnabled,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Updates a pair's borrowing rate % per second
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _borrowingRatePerSecondP new value (1e10, %)
     * @param _signedPairPrices signed pair market prices
     */
    function setBorrowingRatePerSecondP(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex,
        uint24[] calldata _borrowingRatePerSecondP,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Executes pending param update callback using signed prices stored in initial context call
     * @param _paramUpdate param update to execute
     */
    function paramUpdateCallbackWithSignedPrices(IFundingFees.PendingParamUpdate memory _paramUpdate) external;

    /**
     * @dev Stores initial acc funding / borrowing fees for a trade
     * @dev HAS TO BE CALLED when a new trade is opened or when a trade's position size changes (+ store pending holding fees until now separately)
     * @param _trader trader address
     * @param _index index of trade
     * @param _collateralIndex index of collateral
     * @param _pairIndex index of the pair
     * @param _long true if long, false if short
     * @param _currentPairPrice current pair price (1e10)
     */
    function storeTradeInitialAccFees(
        address _trader,
        uint32 _index,
        uint8 _collateralIndex,
        uint16 _pairIndex,
        bool _long,
        uint64 _currentPairPrice
    ) external;

    /**
     * @dev Realizes pending holding fees on an open trade
     * @param _trader trader address
     * @param _index index of trade
     * @param _currentPairPrice current pair price (1e10)
     */
    function realizeHoldingFeesOnOpenTrade(address _trader, uint32 _index, uint64 _currentPairPrice) external;

    /**
     * @dev Stores trade manually realized negative pnl in collateral tokens
     * @param _trader address of trader
     * @param _index index of trade
     * @param _amountCollateral new amount of realized negative pnl in collateral tokens (collateral precision)
     */
    function storeManuallyRealizedNegativePnlCollateral(
        address _trader,
        uint32 _index,
        uint256 _amountCollateral
    ) external;

    /**
     * @dev Realizes pnl on an open trade
     * @param _trader trader address
     * @param _index index of trade
     * @param _pnlCollateral pnl to realize in collateral tokens (collateral precision)
     */
    function realizePnlOnOpenTrade(address _trader, uint32 _index, int256 _pnlCollateral) external;

    /**
     * @dev Realizes trading fees on an open trade
     * @param _trader trader address
     * @param _index index of trade
     * @param _feesCollateral trading fees to charge in collateral tokens (collateral precision)
     * @param _currentPairPrice current pair price (1e10)
     * @return finalFeesCollateral trading fees charged in collateral tokens (collateral precision), same as input unless liquidated then 0
     */
    function realizeTradingFeesOnOpenTrade(
        address _trader,
        uint32 _index,
        uint256 _feesCollateral,
        uint64 _currentPairPrice
    ) external returns (uint256 finalFeesCollateral);

    /**
     * @dev Decreases a trade's realized pnl and available collateral in diamond proportionally to size delta ratio over full size (for partial closes with collateral delta > 0)
     * @param _trader trader address
     * @param _index index of trade
     * @param _positionSizeCollateralDelta position size collateral delta (collateral precision)
     * @param _existingPositionSizeCollateral existing position size collateral (collateral precision)
     * @param _newCollateralAmount new trade collateral amount after partial close (collateral precision)
     */
    function downscaleTradeFeesData(
        address _trader,
        uint32 _index,
        uint256 _positionSizeCollateralDelta,
        uint256 _existingPositionSizeCollateral,
        uint256 _newCollateralAmount
    ) external;

    /**
     * @dev Stores already transferred negative pnl for a trade (for partial closes with leverage delta > 0 and negative PnL)
     * @param _trader address of trader
     * @param _index index of trade
     * @param _deltaCollateral delta in collateral tokens to store (collateral precision)
     */
    function storeAlreadyTransferredNegativePnl(address _trader, uint32 _index, uint256 _deltaCollateral) external;

    /**
     * @dev Stores virtual available collateral in diamond to compensate if available in diamond would be < 0 without it (for collateral withdrawals)
     * @param _trader address of trader
     * @param _index index of trade
     * @param _newTradeCollateralAmount new trade collateral amount (collateral precision)
     */
    function storeVirtualAvailableCollateralInDiamond(
        address _trader,
        uint32 _index,
        uint256 _newTradeCollateralAmount
    ) external;

    /**
     * @dev Stores UI partial close realized pnl for a trade
     * @param _trader address of trader
     * @param _index index of trade
     * @param _deltaCollateral raw pnl realized in collateral tokens (collateral precision)
     */
    function storeUiRealizedPnlPartialCloseCollateral(address _trader, uint32 _index, int256 _deltaCollateral) external;

    /**
     * @dev Stores UI withdrawn pnl for a trade
     * @param _trader address of trader
     * @param _index index of trade
     * @param _deltaCollateral pnl withdrawn in collateral tokens (collateral precision)
     */
    function storeUiPnlWithdrawnCollateral(address _trader, uint32 _index, uint256 _deltaCollateral) external;

    /**
     * @dev Stores UI realized trading fees for a trade
     * @param _trader address of trader
     * @param _index index of trade
     * @param _deltaCollateral realized trading fees in collateral tokens (collateral precision)
     */
    function storeUiRealizedTradingFeesCollateral(address _trader, uint32 _index, uint256 _deltaCollateral) external;

    /**
     * @dev Returns pending funding fees in collateral tokens for an open trade (collateral precision)
     * @param _trader trader address
     * @param _index index of trade
     * @param _currentPairPrice current pair price (1e10)
     */
    function getTradeFundingFeesCollateral(
        address _trader,
        uint32 _index,
        uint64 _currentPairPrice
    ) external view returns (int256);

    /**
     * @dev Returns pending borrowing fees in collateral tokens for an open trade (collateral precision)
     * @param _trader trader address
     * @param _index index of trade
     * @param _currentPairPrice current pair price (1e10)
     */
    function getTradeBorrowingFeesCollateral(
        address _trader,
        uint32 _index,
        uint64 _currentPairPrice
    ) external view returns (uint256);

    /**
     * @dev Returns trade pending funding fees, borrowing fees, old borrowing fees, and total holding fees in collateral tokens (collateral precision)
     * @param _trader trader address
     * @param _index index of trade
     * @param _currentPairPrice current pair price (1e10)
     * @return tradeHoldingFees trade holding fees in collateral tokens (collateral precision)
     */
    function getTradePendingHoldingFeesCollateral(
        address _trader,
        uint32 _index,
        uint64 _currentPairPrice
    ) external view returns (IFundingFees.TradeHoldingFees memory tradeHoldingFees);

    /**
     * @dev Returns pending acc funding fees for a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _currentPairPrice current pair price (1e10)
     * @return accFundingFeeLongP pending acc funding fee % for longs (1e20)
     * @return accFundingFeeShortP pending acc funding fee % for shorts (1e20)
     * @return currentFundingRatePerSecondP current funding rate % per second (1e18)
     */
    function getPairPendingAccFundingFees(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        uint64 _currentPairPrice
    ) external view returns (int128 accFundingFeeLongP, int128 accFundingFeeShortP, int56 currentFundingRatePerSecondP);

    /**
     * @dev Returns pending acc borrowing fees for a pair
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     * @param _currentPairPrice current pair price (1e10)
     * @return accBorrowingFeeP pending acc borrowing fee % (1e20)
     */
    function getPairPendingAccBorrowingFees(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        uint64 _currentPairPrice
    ) external view returns (uint128 accBorrowingFeeP);

    /**
     * @dev Returns max skew in collateral tokens for a pair (1e10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getMaxSkewCollateral(uint8 _collateralIndex, uint16 _pairIndex) external view returns (uint80);

    /**
     * @dev Returns max skew in collateral tokens for pairs (1e10)
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairGlobalParamsArray(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex
    ) external view returns (PairGlobalParams[] memory);

    /**
     * @dev Returns funding fee params for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairFundingFeeParams(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex
    ) external view returns (IFundingFees.FundingFeeParams[] memory);

    /**
     * @dev Returns borrowing fee params for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairBorrowingFeeParams(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex
    ) external view returns (IFundingFees.BorrowingFeeParams[] memory);

    /**
     * @dev Returns funding fee data for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairFundingFeeData(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex
    ) external view returns (IFundingFees.PairFundingFeeData[] memory);

    /**
     * @dev Returns borrowing fee data for pairs
     * @param _collateralIndex index of the collateral
     * @param _pairIndex index of the pair
     */
    function getPairBorrowingFeeData(
        uint8[] calldata _collateralIndex,
        uint16[] calldata _pairIndex
    ) external view returns (IFundingFees.PairBorrowingFeeData[] memory);

    /**
     * @dev Returns fees data for trade
     * @param _trader trader address
     * @param _index trade index
     */
    function getTradeFeesData(address _trader, uint32 _index) external view returns (IFundingFees.TradeFeesData memory);

    /**
     * @dev Returns fees data for trades
     * @param _trader trader address
     * @param _index trade index
     */
    function getTradeFeesDataArray(
        address[] calldata _trader,
        uint32[] calldata _index
    ) external view returns (IFundingFees.TradeFeesData[] memory);

    /**
     * @dev Returns UI realized pnl data for trades
     * @param _trader trader address
     * @param _index trade index
     */
    function getTradeUiRealizedPnlDataArray(
        address[] calldata _trader,
        uint32[] calldata _index
    ) external view returns (IFundingFees.UiRealizedPnlData[] memory);

    /**
     * @dev Returns trade manually realized negative pnl in collateral tokens (collateral precision)
     * @param _trader address of trader
     * @param _index index of trade
     */
    function getTradeManuallyRealizedNegativePnlCollateral(
        address _trader,
        uint32 _index
    ) external view returns (uint256);

    /**
     * @dev Returns pending param updates
     * @param _index update index
     */
    function getPendingParamUpdates(
        uint32[] calldata _index
    ) external view returns (IFundingFees.PendingParamUpdate[] memory);

    /**
     * @dev Returns realized pnl in collateral tokens for an open trade
     * @param _trader trader address
     * @param _index trade index
     * @return realizedPnlCollateral realized pnl in collateral tokens (collateral precision)
     * @return realizedTradingFeesCollateral realized trading fees in collateral tokens (collateral precision)
     * @return totalRealizedPnlCollateral total realized pnl in collateral tokens (collateral precision)
     */
    function getTradeRealizedPnlCollateral(
        address _trader,
        uint32 _index
    )
        external
        view
        returns (
            int256 realizedPnlCollateral,
            uint256 realizedTradingFeesCollateral,
            int256 totalRealizedPnlCollateral
        );

    /**
     * @dev Returns realized trading fees in collateral tokens for an open trade (collateral precision)
     * @param _trader trader address
     * @param _index trade index
     */
    function getTradeRealizedTradingFeesCollateral(address _trader, uint32 _index) external view returns (uint256);

    /**
     * @dev Emitted when a pair's max skew collateral is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param maxSkewCollateral new value (1e10)
     */
    event MaxSkewCollateralUpdated(uint8 indexed collateralIndex, uint16 indexed pairIndex, uint80 maxSkewCollateral);

    /**
     * @dev Emitted when a pair's skew coefficient per year is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param skewCoefficientPerYear new value (1e26)
     */
    event SkewCoefficientPerYearUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint112 skewCoefficientPerYear
    );

    /**
     * @dev Emitted when a pair's absolute velocity per year cap is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param absoluteVelocityPerYearCap new value (1e7)
     */
    event AbsoluteVelocityPerYearCapUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint24 absoluteVelocityPerYearCap
    );

    /**
     * @dev Emitted when a pair's funding rate % per second absolute cap is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param absoluteRatePerSecondCap new value (1e10)
     */
    event AbsoluteRatePerSecondCapUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint24 absoluteRatePerSecondCap
    );

    /**
     * @dev Emitted when a pair's theta USD threshold is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param thetaThresholdUsd new value (USD)
     */
    event ThetaThresholdUsdUpdated(uint8 indexed collateralIndex, uint16 indexed pairIndex, uint32 thetaThresholdUsd);

    /**
     * @dev Emitted when a pair's funding fees are enabled/disabled
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param fundingFeesEnabled new value
     */
    event FundingFeesEnabledUpdated(uint8 indexed collateralIndex, uint16 indexed pairIndex, bool fundingFeesEnabled);

    /**
     * @dev Emitted when a pair's APR multiplier is enabled/disabled
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param aprMultiplierEnabled new value
     */
    event AprMultiplierEnabledUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        bool aprMultiplierEnabled
    );

    /**
     * @dev Emitted when a pair's borrowing rate % per second is updated
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param borrowingRatePerSecondP new value (1e10, %)
     */
    event BorrowingRatePerSecondPUpdated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint24 borrowingRatePerSecondP
    );

    /**
     * @dev Emitted when a pair's pending acc funding fees are stored
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param data pair funding fee data
     */
    event PendingAccFundingFeesStored(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        IFundingFees.PairFundingFeeData data
    );

    /**
     * @dev Emitted when a pair's pending acc borrowing fees are stored
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param data pair borrowing fee data
     */
    event PendingAccBorrowingFeesStored(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        IFundingFees.PairBorrowingFeeData data
    );

    /**
     * @dev Emitted when a trade's initial acc fees are stored or reset
     * @param trader trader address
     * @param index index of trade
     * @param collateralIndex index of collateral
     * @param pairIndex index of the pair
     * @param long true if long, false if short
     * @param currentPairPrice current pair price (1e10)
     * @param newInitialAccFundingFeeP new initial acc funding fee % (1e20)
     * @param newInitialAccBorrowingFeeP new initial acc borrowing fee % (1e20)
     */
    event TradeInitialAccFeesStored(
        address indexed trader,
        uint32 indexed index,
        uint8 collateralIndex,
        uint16 pairIndex,
        bool long,
        uint64 currentPairPrice,
        int128 newInitialAccFundingFeeP,
        uint128 newInitialAccBorrowingFeeP
    );

    /**
     * @dev Emitted when holding fees are realized (earned) on an open trade
     * @param collateralIndex index of the collateral
     * @param trader trader address
     * @param index index of trade
     * @param currentPairPrice current pair price (1e10)
     * @param tradeHoldingFees trade holding fees in collateral tokens (collateral precision)
     * @param newRealizedPnlCollateral new realized pnl value for trade in collateral tokens (collateral precision)
     */
    event HoldingFeesRealizedOnTrade(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        uint64 currentPairPrice,
        IFundingFees.TradeHoldingFees tradeHoldingFees,
        int256 newRealizedPnlCollateral
    );

    /**
     * @dev Emitted when holding fees are realized (charged) on an open trade
     * @param collateralIndex index of the collateral
     * @param trader trader address
     * @param index index of trade
     * @param currentPairPrice current pair price (1e10)
     * @param tradeHoldingFees trade holding fees in collateral tokens (collateral precision)
     * @param availableCollateralInDiamond trade available collateral in diamond contract (collateral precision)
     * @param amountSentToVaultCollateral amount sent to vault in collateral tokens (collateral precision)
     * @param newRealizedTradingFeesCollateral new realized trading fees in collateral tokens (collateral precision)
     * @param newRealizedPnlCollateral new realized pnl in collateral tokens (collateral precision)
     */
    event HoldingFeesChargedOnTrade(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        uint64 currentPairPrice,
        IFundingFees.TradeHoldingFees tradeHoldingFees,
        uint256 availableCollateralInDiamond,
        uint256 amountSentToVaultCollateral,
        uint256 newRealizedTradingFeesCollateral,
        int256 newRealizedPnlCollateral
    );

    /**
     * @dev Emitted when negative pnl is manually realized on an open trade
     * @param trader trader address
     * @param index trade index
     * @param newManuallyRealizedNegativePnlCollateral new manually realized negative pnl in collateral tokens (collateral precision)
     */
    event ManuallyRealizedNegativePnlCollateralStored(
        address indexed trader,
        uint32 indexed index,
        uint128 newManuallyRealizedNegativePnlCollateral
    );

    /**
     * @dev Emitted when pnl is realized on an open trade
     * @param trader trader address
     * @param index index of trade
     * @param pnlCollateral pnl realized in collateral tokens (collateral precision)
     * @param newRealizedPnlCollateral new realized pnl value for trade in collateral tokens (collateral precision)
     */
    event PnlRealizedOnOpenTrade(
        address indexed trader,
        uint32 indexed index,
        int256 pnlCollateral,
        int256 newRealizedPnlCollateral
    );

    /**
     * @dev Emitted when trading fees are realized on an open trade
     * @param collateralIndex index of the collateral
     * @param trader trader address
     * @param index index of trade
     * @param tradingFeesCollateral trading fees input in collateral tokens (collateral precision)
     * @param finalTradingFeesCollateral trading fees realized in collateral tokens (collateral precision)
     * @param newRealizedFeesCollateral new realized fees value for trade in collateral tokens (collateral precision)
     * @param newRealizedPnlCollateral new realized pnl value for trade in collateral tokens (collateral precision)
     * @param amountSentFromVaultCollateral amount sent from vault in collateral tokens (collateral precision)
     */
    event TradingFeesRealized(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        uint256 tradingFeesCollateral,
        uint256 finalTradingFeesCollateral,
        uint256 newRealizedFeesCollateral,
        int256 newRealizedPnlCollateral,
        uint256 amountSentFromVaultCollateral
    );

    /**
     * @dev Emitted when a trade's realized pnl and available in diamond is scaled down
     * @param trader trader address
     * @param index trade index
     * @param positionSizeCollateralDelta position size collateral delta (collateral precision)
     * @param existingPositionSizeCollateral existing position size collateral (collateral precision)
     * @param newCollateralAmount new trade collateral amount (collateral precision)
     * @param newTradeFeesData new trade fees data
     */
    event TradeFeesDataDownscaled(
        address indexed trader,
        uint32 indexed index,
        uint256 positionSizeCollateralDelta,
        uint256 existingPositionSizeCollateral,
        uint256 newCollateralAmount,
        IFundingFees.TradeFeesData newTradeFeesData
    );

    /**
     * @dev Emitted when a trade's already transferred negative pnl is stored
     * @param trader trader address
     * @param index trade index
     * @param deltaCollateral delta in collateral tokens to store (collateral precision)
     * @param newAlreadyTransferredNegativePnlCollateral new already transferred negative pnl in collateral tokens (collateral precision)
     */
    event AlreadyTransferredNegativePnlStored(
        address indexed trader,
        uint32 indexed index,
        uint256 deltaCollateral,
        uint128 newAlreadyTransferredNegativePnlCollateral
    );

    /**
     * @dev Emitted when a trade's virtual available collateral in diamond is stored
     * @param trader trader address
     * @param index trade index
     * @param newTradeCollateralAmount new trade collateral amount (collateral precision)
     * @param currentManuallyRealizedNegativePnlCollateral current manually realized negative pnl collateral value (collateral precision)
     * @param manuallyRealizedNegativePnlCollateralCapped whether manually realized negative pnl collateral value was capped (collateral precision)
     * @param virtualAvailableCollateralInDiamondDelta virtual available collateral in diamond delta to keep available collateral in diamond >= 0 (collateral precision)
     * @param newVirtualAvailableCollateralInDiamond new virtual available collateral in diamond (collateral precision)
     */
    event VirtualAvailableCollateralInDiamondStored(
        address indexed trader,
        uint32 indexed index,
        uint256 newTradeCollateralAmount,
        uint256 currentManuallyRealizedNegativePnlCollateral,
        bool manuallyRealizedNegativePnlCollateralCapped,
        uint256 virtualAvailableCollateralInDiamondDelta,
        uint256 newVirtualAvailableCollateralInDiamond
    );

    /**
     * @dev Emitted when a param update is requested
     * @param collateralIndex index of the collateral
     * @param pairIndex index of the pair
     * @param updateType type of update
     * @param newValue new value
     */
    event ParamUpdateRequested(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        IFundingFees.ParamUpdateType updateType,
        uint224 newValue
    );
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IOtc.sol";

/**
 * @dev Interface for GNSOtc facet (inherits types and also contains functions, events, and custom errors)
 */
interface IOtcUtils is IOtc {
    /**
     * @dev Initializer for OTC facet
     * @param _config new OTC Config
     */
    function initializeOtc(IOtcUtils.OtcConfig memory _config) external;

    /**
     * @dev Updates OTC config
     * @param _config new OTC Config. Sum of `treasuryShareP`, `stakingShareP`, `burnShareP` must equal 100 and `premiumP` must be less than or equal to MAX_PREMIUM_P
     */
    function updateOtcConfig(IOtcUtils.OtcConfig memory _config) external;

    /**
     * @dev Increases OTC balance for a collateral
     * @param _collateralIndex collateral index
     * @param _collateralAmount amount of collateral to increase (collateral precision)
     */
    function addOtcCollateralBalance(uint8 _collateralIndex, uint256 _collateralAmount) external;

    /**
     * @dev OTC Buys GNS from caller for `_amountCollateral` of `_collateralIndex`.
     * When collateral is GNS, no tokens are transferred to or from the caller and no premium is paid.
     *
     * @param _collateralIndex collateral index
     * @param _collateralAmount amount of collateral to trade (collateral precision)
     */
    function sellGnsForCollateral(uint8 _collateralIndex, uint256 _collateralAmount) external;

    /**
     * @dev Returns OTC Config
     */
    function getOtcConfig() external view returns (IOtcUtils.OtcConfig memory);

    /**
     * @dev Returns OTC balance for a collateral (collateral precision)
     * @param _collateralIndex collateral index
     */
    function getOtcBalance(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Returns OTC rate (price + premium) of GNS in collateral (1e10)
     * @param _collateralIndex collateral index
     */
    function getOtcRate(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Emitted when OTCConfig is updated
     * @param config new OTC config
     */
    event OtcConfigUpdated(IOtcUtils.OtcConfig config);

    /**
     * @dev Emitted when OTC balance is updated
     * @param collateralIndex collateral index
     * @param balanceCollateral new balance (collateral precision)
     */
    event OtcBalanceUpdated(uint8 indexed collateralIndex, uint256 balanceCollateral);

    /**
     * @dev Emitted when an OTC trade is executed
     * @param collateralIndex collateral index
     * @param collateralAmount amount of collateral traded (collateral precision)
     * @param gnsPriceCollateral effective gns/collateral price, including premium (1e10)
     * @param treasuryAmountGns amount of GNS sent to treasury (1e18)
     * @param stakingAmountGns amount of GNS sent to GNS Staking (1e18)
     * @param burnAmountGns amount of GNS burned (1e18)
     */
    event OtcExecuted(
        uint8 indexed collateralIndex,
        uint256 collateralAmount,
        uint256 gnsPriceCollateral,
        uint256 treasuryAmountGns,
        uint256 stakingAmountGns,
        uint256 burnAmountGns
    );

    error InvalidShareSum();
}

File 23 of 51 : IPairsStorageUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IPairsStorage.sol";

/**
 * @dev Interface for GNSPairsStorage facet (inherits types and also contains functions, events, and custom errors)
 */
interface IPairsStorageUtils is IPairsStorage {
    /**
     * @dev Initializes liquidation params for all existing groups
     * @param _groupLiquidationParams liquidation params for each group (index corresponds to group index)
     */
    function initializeGroupLiquidationParams(
        IPairsStorage.GroupLiquidationParams[] memory _groupLiquidationParams
    ) external;

    /**
     * @dev Copies all existing fee groups to new mapping, multiplies existing groups min/max lev by 1e3, initializes new global trade fee params
     * @param _tradeFeeParams global trade fee params
     */
    function initializeNewFees(IPairsStorage.GlobalTradeFeeParams memory _tradeFeeParams) external;

    /**
     * @dev Initializes referral fee change (adds 50% of referral share to gov and otc, now gov+otc+trigger+gToken = 100%, referral fee charged first)
     * @dev Only useful for v9.4.4 -> v9.4.5 transition
     */
    function initializeReferralFeeChange() external;

    /**
     * @dev Adds new trading pairs
     * @param _pairs pairs to add
     */
    function addPairs(Pair[] calldata _pairs) external;

    /**
     * @dev Updates trading pairs
     * @param _pairIndices indices of pairs
     * @param _pairs new pairs values
     */
    function updatePairs(uint256[] calldata _pairIndices, Pair[] calldata _pairs) external;

    /**
     * @dev Adds new pair groups
     * @param _groups groups to add
     */
    function addGroups(Group[] calldata _groups) external;

    /**
     * @dev Updates pair groups
     * @param _ids indices of groups
     * @param _groups new groups values
     */
    function updateGroups(uint256[] calldata _ids, Group[] calldata _groups) external;

    /**
     * @dev Adds new pair fees groups
     * @param _fees fees to add
     */
    function addFees(FeeGroup[] calldata _fees) external;

    /**
     * @dev Updates pair fees groups
     * @param _ids indices of fees
     * @param _fees new fees values
     */
    function updateFees(uint256[] calldata _ids, FeeGroup[] calldata _fees) external;

    /**
     * @dev Updates pair custom max leverages (if unset group default is used); useful to delist a pair if new value is below the pair's group minLeverage
     * @param _indices indices of pairs
     * @param _values new custom max leverages (1e3 precision)
     */
    function setPairCustomMaxLeverages(uint256[] calldata _indices, uint256[] calldata _values) external;

    /**
     * @dev Updates group liquidation params (will only apply for trades opened after the change)
     * @param _groupIndex index of group
     * @param _params new liquidation params
     */
    function setGroupLiquidationParams(
        uint256 _groupIndex,
        IPairsStorage.GroupLiquidationParams memory _params
    ) external;

    /**
     * @dev Updates global trade fee params
     * @param _feeParams new fee params
     */
    function setGlobalTradeFeeParams(IPairsStorage.GlobalTradeFeeParams memory _feeParams) external;

    /**
     * @dev Updates pairs counter trade max leverage
     * @param _indices indices of pairs
     * @param _values new max leverages (1e3), 0 disables counter trades for the pair
     */
    function setPairCounterTradeMaxLeverages(uint16[] calldata _indices, uint24[] calldata _values) external;

    /**
     * @dev Updates counter trade fee rate multiplier
     * @param _indices indices of pairs
     * @param _values new multipliers (1e3), 1e3 disables counter trade discount
     */
    function setPairCounterTradeFeeRateMultipliers(uint16[] calldata _indices, uint16[] calldata _values) external;

    /**
     * @dev Returns data needed by price aggregator when doing a new price request
     * @param _pairIndex index of pair
     * @return from pair from (eg. BTC)
     * @return to pair to (eg. USD)
     */
    function pairJob(uint256 _pairIndex) external view returns (string memory from, string memory to);

    /**
     * @dev Returns whether a pair is listed
     * @param _from pair from (eg. BTC)
     * @param _to pair to (eg. USD)
     */
    function isPairListed(string calldata _from, string calldata _to) external view returns (bool);

    /**
     * @dev Returns whether a pair index is listed
     * @param _pairIndex index of pair to check
     */
    function isPairIndexListed(uint256 _pairIndex) external view returns (bool);

    /**
     * @dev Returns a pair's details
     * @param _index index of pair
     */
    function pairs(uint256 _index) external view returns (Pair memory);

    /**
     * @dev Returns number of listed pairs
     */
    function pairsCount() external view returns (uint256);

    /**
     * @dev Returns the sum of trader's custom spread + global pair's spread % (1e10 precision)
     * @param _trader trader address
     * @param _pairIndex index of pair
     */
    function pairSpreadP(address _trader, uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns array of each traders' custom spread + global pair's spread % (1e10 precision)
     * @param _trader array of traders
     * @param _pairIndex array of pairs indices
     */
    function pairSpreadPArray(
        address[] calldata _trader,
        uint256[] calldata _pairIndex
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns a pair's min leverage (1e3 precision)
     * @param _pairIndex index of pair
     */
    function pairMinLeverage(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a pair's total position size fee % (1e10 precision)
     * @param _pairIndex index of pair
     */
    function pairTotalPositionSizeFeeP(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a pair's total liquidation collateral fee % (1e10 precision)
     * @param _pairIndex index of pair
     */
    function pairTotalLiqCollateralFeeP(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a pair's oracle position size fee % (1e10 precision)
     * @param _pairIndex index of pair
     */
    function pairOraclePositionSizeFeeP(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a pair's min position size in USD (1e18 precision)
     * @param _pairIndex index of pair
     */
    function pairMinPositionSizeUsd(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns global trade fee params
     */
    function getGlobalTradeFeeParams() external view returns (IPairsStorage.GlobalTradeFeeParams memory);

    /**
     * @dev Returns a pair's minimum trading fee in USD (1e18 precision)
     * @param _pairIndex index of pair
     */
    function pairMinFeeUsd(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a group details
     * @param _index index of group
     */
    function groups(uint256 _index) external view returns (Group memory);

    /**
     * @dev Returns number of listed groups
     */
    function groupsCount() external view returns (uint256);

    /**
     * @dev Returns a fee group details
     * @param _index index of fee group
     */
    function fees(uint256 _index) external view returns (FeeGroup memory);

    /**
     * @dev Returns number of listed fee groups
     */
    function feesCount() external view returns (uint256);

    /**
     * @dev Returns a pair's active max leverage; custom if set, otherwise group default (1e3 precision)
     * @param _pairIndex index of pair
     */
    function pairMaxLeverage(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns a pair's custom max leverage; 0 if not set (1e3 precision)
     * @param _pairIndex index of pair
     */
    function pairCustomMaxLeverage(uint256 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns all listed pairs custom max leverages (1e3 precision)
     */
    function getAllPairsRestrictedMaxLeverage() external view returns (uint256[] memory);

    /**
     * @dev Returns a group's liquidation params
     */
    function getGroupLiquidationParams(
        uint256 _groupIndex
    ) external view returns (IPairsStorage.GroupLiquidationParams memory);

    /**
     * @dev Returns a pair's group liquidation params
     */
    function getPairLiquidationParams(
        uint256 _pairIndex
    ) external view returns (IPairsStorage.GroupLiquidationParams memory);

    /**
     * @dev Returns a pair's counter trade max leverage (1e3)
     * @param _pairIndex index of pair
     */
    function getPairCounterTradeMaxLeverage(uint16 _pairIndex) external view returns (uint24);

    /**
     * @dev Returns multiple pairs counter trade max leverage (1e3)
     * @param _pairIndex indices of pairs
     */
    function getPairCounterTradeMaxLeverages(uint16[] calldata _pairIndex) external view returns (uint24[] memory);

    /**
     * @dev Returns a pair's counter trade fee rate multiplier (1e3)
     * @param _pairIndex index of pair
     */
    function getPairCounterTradeFeeRateMultiplier(uint16 _pairIndex) external view returns (uint16);

    /**
     * @dev Returns multiple pairs counter trade fee rate multipliers (1e3)
     * @param _pairIndex indices of pairs
     */
    function getPairCounterTradeFeeRateMultipliers(
        uint16[] calldata _pairIndex
    ) external view returns (uint16[] memory);

    /**
     * @dev Returns the effective total position size fee % (1e10 precision) after counter trade multiplier where applicable
     * @param _pairIndex index of pair
     * @param _isCounterTrade whether the trade is a counter trade
     */
    function getEffectiveTotalPositionSizeFeeP(uint16 _pairIndex, bool _isCounterTrade) external view returns (uint256);

    /**
     * @dev Emitted when a new pair is listed
     * @param index index of pair
     * @param from pair from (eg. BTC)
     * @param to pair to (eg. USD)
     */
    event PairAdded(uint256 index, string from, string to);

    /**
     * @dev Emitted when a pair is updated
     * @param index index of pair
     */
    event PairUpdated(uint256 index);

    /**
     * @dev Emitted when a pair's custom max leverage is updated
     * @param index index of pair
     * @param maxLeverage new max leverage (1e3 precision)
     */
    event PairCustomMaxLeverageUpdated(uint256 indexed index, uint256 maxLeverage);

    /**
     * @dev Emitted when a new group is added
     * @param index index of group
     * @param name name of group
     */
    event GroupAdded(uint256 index, string name);

    /**
     * @dev Emitted when a group is updated
     * @param index index of group
     */
    event GroupUpdated(uint256 index);

    /**
     * @dev Emitted when a new fee group is added
     * @param index index of fee group
     * @param feeGroup fee group
     */
    event FeeAdded(uint256 index, FeeGroup feeGroup);

    /**
     * @dev Emitted when a fee group is updated
     * @param index index of fee group
     * @param feeGroup updated fee group
     */
    event FeeUpdated(uint256 index, FeeGroup feeGroup);

    /**
     * @dev Emitted when a group liquidation params are updated
     * @param index index of group
     * @param params new group liquidation params
     */
    event GroupLiquidationParamsUpdated(uint256 index, IPairsStorage.GroupLiquidationParams params);

    /**
     * @dev Emitted when global trade fee params are updated
     * @param feeParams new fee params
     */
    event GlobalTradeFeeParamsUpdated(IPairsStorage.GlobalTradeFeeParams feeParams);

    /**
     * @dev Emitted when a pair's counter trade max leverage is updated
     * @param pairIndex index of pair
     * @param newValue new max leverage (1e3)
     */
    event CounterTradeMaxLeverageUpdated(uint16 indexed pairIndex, uint24 newValue);

    /**
     * @dev Emitted when counter trade fee rate multiplier is updated
     * @param newValue new multiplier (1e3)
     */
    event CounterTradeFeeRateMultiplierUpdated(uint16 indexed pairIndex, uint16 newValue);

    error PairNotListed();
    error GroupNotListed();
    error FeeNotListed();
    error WrongLeverages();
    error WrongFees();
    error PairAlreadyListed();
    error MaxLiqSpreadPTooHigh();
    error WrongLiqParamsThresholds();
    error WrongLiqParamsLeverages();
    error StartLiqThresholdTooHigh();
    error EndLiqThresholdTooLow();
    error StartLeverageTooLow();
    error EndLeverageTooHigh();
}

File 24 of 51 : IPriceAggregatorUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {Chainlink} from "@chainlink/contracts/src/v0.8/Chainlink.sol";

import "../types/IPriceAggregator.sol";
import "../types/ITradingStorage.sol";
import "../types/ITradingCallbacks.sol";

/**
 * @dev Interface for GNSPriceAggregator facet (inherits types and also contains functions, events, and custom errors)
 */
interface IPriceAggregatorUtils is IPriceAggregator {
    /**
     * @dev Initializes price aggregator facet
     * @param _linkToken LINK token address
     * @param _linkUsdPriceFeed LINK/USD price feed address
     * @param _twapInterval TWAP interval (seconds)
     * @param _minAnswers answers count at which a trade is executed with median
     * @param _oracles chainlink oracle addresses
     * @param _jobIds chainlink job ids (market/lookback)
     * @param _collateralIndices collateral indices
     * @param _gnsCollateralLiquidityPools corresponding GNS/collateral liquidity pool values
     * @param _collateralUsdPriceFeeds corresponding collateral/USD chainlink price feeds
     */
    function initializePriceAggregator(
        address _linkToken,
        IChainlinkFeed _linkUsdPriceFeed,
        uint24 _twapInterval,
        uint8 _minAnswers,
        address[] memory _oracles,
        bytes32[2] memory _jobIds,
        uint8[] calldata _collateralIndices,
        LiquidityPoolInput[] memory _gnsCollateralLiquidityPools,
        IChainlinkFeed[] memory _collateralUsdPriceFeeds
    ) external;

    /**
     * @dev Initializes lookback job count
     * @param _limitJobCount lookback job count
     */
    function initializeLimitJobCount(uint8 _limitJobCount) external;

    /**
     * @dev Initializes max deviation percentages
     * @param _maxMarketDeviationP max market order deviation percentage (1e3, %)
     * @param _maxLookbackDeviationP max lookback order deviation percentage (1e3, %)
     */
    function initializeMaxDeviationsP(uint24 _maxMarketDeviationP, uint24 _maxLookbackDeviationP) external;

    /**
     * @dev Updates LINK/USD chainlink price feed
     * @param _value new value
     */
    function updateLinkUsdPriceFeed(IChainlinkFeed _value) external;

    /**
     * @dev Updates collateral/USD chainlink price feed
     * @param _collateralIndex collateral index
     * @param _value new value
     */
    function updateCollateralUsdPriceFeed(uint8 _collateralIndex, IChainlinkFeed _value) external;

    /**
     * @dev Updates collateral/GNS liquidity pool
     * @param _collateralIndex collateral index
     * @param _liquidityPoolInput new values
     */
    function updateCollateralGnsLiquidityPool(
        uint8 _collateralIndex,
        LiquidityPoolInput calldata _liquidityPoolInput
    ) external;

    /**
     * @dev Updates TWAP interval
     * @param _twapInterval new value (seconds)
     */
    function updateTwapInterval(uint24 _twapInterval) external;

    /**
     * @dev Updates minimum answers count
     * @param _value new value
     */
    function updateMinAnswers(uint8 _value) external;

    /**
     * @dev Adds an oracle
     * @param _a new value
     */
    function addOracle(address _a) external;

    /**
     * @dev Replaces an oracle
     * @param _index oracle index
     * @param _a new value
     */
    function replaceOracle(uint256 _index, address _a) external;

    /**
     * @dev Removes an oracle
     * @param _index oracle index
     */
    function removeOracle(uint256 _index) external;

    /**
     * @dev Updates market job id
     * @param _jobId new value
     */
    function setMarketJobId(bytes32 _jobId) external;

    /**
     * @dev Updates lookback job id
     * @param _jobId new value
     */
    function setLimitJobId(bytes32 _jobId) external;

    /**
     * @dev Updates lookback job count
     * @param _limitJobCount new value
     */
    function setLimitJobCount(uint8 _limitJobCount) external;

    /**
     * @dev Updates max market order deviation percentage
     * @param _maxMarketDeviationP new value (1e3, %)
     */
    function setMaxMarketDeviationP(uint24 _maxMarketDeviationP) external;

    /**
     * @dev Updates max lookback order deviation percentage
     * @param _maxLookbackDeviationP new value (1e3, %)
     */
    function setMaxLookbackDeviationP(uint24 _maxLookbackDeviationP) external;

    /**
     * @dev Stores pending order, requests price from oracles, and returns pending order id
     * @param _input price request input (see IPriceAggregator)
     */
    function getPrice(IPriceAggregator.GetPriceInput memory _input) external returns (ITradingStorage.Id memory);

    /**
     * @dev Fulfills price request, called by chainlink oracles
     * @param _requestId request id
     * @param _priceData price data
     */
    function fulfill(bytes32 _requestId, uint256 _priceData) external;

    /**
     * @dev Claims back LINK tokens, called by gov fund
     */
    function claimBackLink() external;

    /**
     * @dev Validates signed pair prices, stores them temporarily as well as the corresponding median price for each pair after filtering outliers and the list of corresponding pair indices (for cleanup)
     * @param _signedPairPrices signed pair market prices (one entry per oracle)
     * @param _isLookback whether the prices are for a lookback order
     */
    function validateSignedPairPrices(
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices,
        bool _isLookback
    ) external;

    /**
     * @dev Cleans up all temporary storage related to signed pair prices
     */
    function cleanUpSignedPairPrices() external;

    /**
     * @dev Returns LINK fee for price request
     * @param _collateralIndex collateral index
     * @param _trader trader address
     * @param _pairIndex pair index
     * @param _positionSizeCollateral position size in collateral tokens (collateral precision)
     * @param _isCounterTrade whether corresponding trade is counter trade
     */
    function getLinkFee(
        uint8 _collateralIndex,
        address _trader,
        uint16 _pairIndex,
        uint256 _positionSizeCollateral,
        bool _isCounterTrade
    ) external view returns (uint256);

    /**
     * @dev Returns collateral/USD price
     * @param _collateralIndex index of collateral
     */
    function getCollateralPriceUsd(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Returns USD normalized value from collateral value
     * @param _collateralIndex index of collateral
     * @param _collateralValue collateral value (collateral precision)
     */
    function getUsdNormalizedValue(uint8 _collateralIndex, uint256 _collateralValue) external view returns (uint256);

    /**
     * @dev Returns collateral value (collateral precision) from USD normalized value
     * @param _collateralIndex index of collateral
     * @param _normalizedValue normalized value (1e18 USD)
     */
    function getCollateralFromUsdNormalizedValue(
        uint8 _collateralIndex,
        uint256 _normalizedValue
    ) external view returns (uint256);

    /**
     * @dev Returns GNS/USD price based on GNS/collateral price
     * @param _collateralIndex index of collateral
     */
    function getGnsPriceUsd(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Returns GNS/USD price based on GNS/collateral price
     * @param _collateralIndex index of collateral
     * @param _gnsPriceCollateral GNS/collateral price (1e10)
     */
    function getGnsPriceUsd(uint8 _collateralIndex, uint256 _gnsPriceCollateral) external view returns (uint256);

    /**
     * @dev Returns GNS/collateral price
     * @param _collateralIndex index of collateral
     */
    function getGnsPriceCollateralIndex(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Returns GNS/collateral price
     * @param _collateral address of the collateral
     */
    function getGnsPriceCollateralAddress(address _collateral) external view returns (uint256);

    /**
     * @dev Returns the link/usd price feed address
     */
    function getLinkUsdPriceFeed() external view returns (IChainlinkFeed);

    /**
     * @dev Returns the twap interval in seconds
     */
    function getTwapInterval() external view returns (uint24);

    /**
     * @dev Returns the minimum answers to execute an order and take the median
     */
    function getMinAnswers() external view returns (uint8);

    /**
     * @dev Returns the market job id
     */
    function getMarketJobId() external view returns (bytes32);

    /**
     * @dev Returns the limit job id
     */
    function getLimitJobId() external view returns (bytes32);

    /**
     * @dev Returns a specific oracle
     * @param _index index of the oracle
     */
    function getOracle(uint256 _index) external view returns (address);

    /**
     * @dev Returns all oracles
     */
    function getOracles() external view returns (address[] memory);

    /**
     * @dev Returns collateral/gns liquidity pool info
     * @param _collateralIndex index of collateral
     */
    function getCollateralGnsLiquidityPool(uint8 _collateralIndex) external view returns (LiquidityPoolInfo memory);

    /**
     * @dev Returns collateral/usd chainlink price feed
     * @param _collateralIndex index of collateral
     */
    function getCollateralUsdPriceFeed(uint8 _collateralIndex) external view returns (IChainlinkFeed);

    /**
     * @dev Returns order data
     * @param _requestId index of collateral
     */
    function getPriceAggregatorOrder(bytes32 _requestId) external view returns (Order memory);

    /**
     * @dev Returns order data
     * @param _orderId order id
     */
    function getPriceAggregatorOrderAnswers(
        ITradingStorage.Id calldata _orderId
    ) external view returns (OrderAnswer[] memory);

    /**
     * @dev Returns chainlink token address
     */
    function getChainlinkToken() external view returns (address);

    /**
     * @dev Returns requestCount (used by ChainlinkClientUtils)
     */
    function getRequestCount() external view returns (uint256);

    /**
     * @dev Returns pendingRequests mapping entry (used by ChainlinkClientUtils)
     */
    function getPendingRequest(bytes32 _id) external view returns (address);

    /**
     * @dev Returns lookback job count
     */
    function getLimitJobCount() external view returns (uint8);

    /**
     * @dev Returns current lookback job index
     */
    function getLimitJobIndex() external view returns (uint88);

    /**
     * @dev Returns max market order deviation percentage (1e3 %)
     */
    function getMaxMarketDeviationP() external view returns (uint24);

    /**
     * @dev Returns max lookback order deviation percentage (1e3 %)
     */
    function getMaxLookbackDeviationP() external view returns (uint24);

    /**
     * @dev Returns temporary signed order answers for a pair
     * @param _pairIndex pair index
     */
    function getPairSignedOrderAnswersTemporary(
        uint16 _pairIndex
    ) external view returns (IPriceAggregator.OrderAnswer[] memory);

    /**
     * @dev Returns the median signed answer for a pair based on temporary storage
     * @param _pairIndex pair index
     */
    function getPairSignedMedianTemporary(
        uint16 _pairIndex
    ) external view returns (ITradingCallbacks.AggregatorAnswer memory);

    /**
     * @dev Returns signed pair indices stored temporarily (for cleanup)
     */
    function getSignedPairIndicesTemporary() external view returns (uint16[] memory);

    /**
     * @dev Emitted when LINK/USD price feed is updated
     * @param value new value
     */
    event LinkUsdPriceFeedUpdated(address value);

    /**
     * @dev Emitted when collateral/USD price feed is updated
     * @param collateralIndex collateral index
     * @param value new value
     */
    event CollateralUsdPriceFeedUpdated(uint8 collateralIndex, address value);

    /**
     * @dev Emitted when collateral/GNS Uniswap V3 pool is updated
     * @param collateralIndex collateral index
     * @param newValue new value
     */
    event CollateralGnsLiquidityPoolUpdated(uint8 collateralIndex, LiquidityPoolInfo newValue);

    /**
     * @dev Emitted when TWAP interval is updated
     * @param newValue new value
     */
    event TwapIntervalUpdated(uint32 newValue);

    /**
     * @dev Emitted when minimum answers count is updated
     * @param value new value
     */
    event MinAnswersUpdated(uint8 value);

    /**
     * @dev Emitted when an oracle is added
     * @param index new oracle index
     * @param value value
     */
    event OracleAdded(uint256 index, address value);

    /**
     * @dev Emitted when an oracle is replaced
     * @param index oracle index
     * @param oldOracle old value
     * @param newOracle new value
     */
    event OracleReplaced(uint256 index, address oldOracle, address newOracle);

    /**
     * @dev Emitted when an oracle is removed
     * @param index oracle index
     * @param oldOracle old value
     */
    event OracleRemoved(uint256 index, address oldOracle);

    /**
     * @dev Emitted when market job id is updated
     * @param index index
     * @param jobId new value
     */
    event JobIdUpdated(uint256 index, bytes32 jobId);

    /**
     * @dev Emitted when a chainlink request is created
     * @param request link request details
     */
    event LinkRequestCreated(Chainlink.Request request);

    /**
     * @dev Emitted when a price is requested to the oracles
     * @param collateralIndex collateral index
     * @param pairIndex trading pair index
     * @param pendingOrder corresponding pending order
     * @param positionSizeCollateral position size in collateral tokens (collateral precision)
     * @param fromBlock block number from which to start fetching prices (for lookbacks)
     * @param isCounterTrade whether corresponding trade is counter trade
     * @param isLookback true if lookback
     * @param job chainlink job id (market/lookback)
     * @param linkFeePerNode link fee distributed per node (1e18 precision)
     * @param nodesCount amount of nodes to fetch prices from
     */
    event PriceRequested(
        uint8 indexed collateralIndex,
        uint256 indexed pairIndex,
        ITradingStorage.PendingOrder pendingOrder,
        uint256 positionSizeCollateral,
        uint256 fromBlock,
        bool isCounterTrade,
        bool isLookback,
        bytes32 job,
        uint256 linkFeePerNode,
        uint256 nodesCount
    );

    /**
     * @dev Emitted when a trading callback is called from the price aggregator
     * @param a aggregator answer data
     * @param orderType order type
     */
    event TradingCallbackExecuted(ITradingCallbacks.AggregatorAnswer a, ITradingStorage.PendingOrderType orderType);

    /**
     * @dev Emitted when a price is received from the oracles
     * @param orderId pending order id
     * @param pairIndex trading pair index
     * @param request chainlink request id
     * @param priceData OrderAnswer compressed into uint256
     * @param isLookback true if lookback
     * @param usedInMedian false if order already fulfilled
     * @param minAnswersReached true if min answers count was reached
     * @param minFilteredAnswersReached true if min answers reached after filtering the ones above max deviation
     * @param unfilteredAnswers unfiltered oracle answers (1e10)
     * @param filteredAnswers filtered oracle answers (1e10)
     */
    event PriceReceived(
        ITradingStorage.Id orderId,
        uint16 indexed pairIndex,
        bytes32 request,
        uint256 priceData,
        bool isLookback,
        bool usedInMedian,
        bool minAnswersReached,
        bool minFilteredAnswersReached,
        IPriceAggregator.OrderAnswer[] unfilteredAnswers,
        IPriceAggregator.OrderAnswer[] filteredAnswers
    );

    /**
     * @dev Emitted when all signed prices have been processed for a pair
     * @param pairIndex trading pair index
     * @param isLookback true if lookback
     * @param fromBlock corresponding from block (for lookbacks)
     * @param minFilteredAnswersReached true if min answers reached after filtering the ones above max deviation
     * @param unfilteredAnswers unfiltered oracle answers (1e10)
     * @param filteredAnswers filtered oracle answers (1e10)
     */
    event SignedPricesReceived(
        uint16 indexed pairIndex,
        bool isLookback,
        uint32 fromBlock,
        bool minFilteredAnswersReached,
        IPriceAggregator.OrderAnswer[] unfilteredAnswers,
        IPriceAggregator.OrderAnswer[] filteredAnswers
    );

    /**
     * @dev Emitted when LINK tokens are claimed back by gov fund
     * @param amountLink amount of LINK tokens claimed back
     */
    event LinkClaimedBack(uint256 amountLink);

    /**
     * @dev Emitted when the count of limit jobs is updated
     * @param limitJobCount the count of limit jobs
     */
    event LimitJobCountUpdated(uint8 limitJobCount);

    /**
     * @dev Emitted when max market order deviation percentage is updated
     * @param maxMarketDeviationP new value (1e3, %)
     */
    event MaxMarketDeviationPUpdated(uint24 maxMarketDeviationP);

    /**
     * @dev Emitted when max lookback order deviation percentage is updated
     * @param maxLookbackDeviationP new value (1e3, %)
     */
    event MaxLookbackDeviationPUpdated(uint24 maxLookbackDeviationP);

    error TransferAndCallToOracleFailed();
    error SourceNotOracleOfRequest();
    error RequestAlreadyPending();
    error OracleAlreadyListed();
    error InvalidCandle();
    error WrongCollateralUsdDecimals();
    error InvalidPoolType();
    error WrongSignaturesCount();
    error WrongSignerIdOrder();
    error InvalidExpiryTimestamp();
    error LookbackMismatch();
    error FromBlockMismatch();
    error InvalidSignature();
    error PairAndCurrentPriceLengthMismatch();
    error PairLengthMismatchBetweenSigners();
    error PairIndexMismatchBetweenSigners();
    error DuplicateOrUnsortedPairIndices();
    error ExpiryTooFar();
    error InvalidCurrentPrice();
    error MinAnswersNotReached();
}

File 25 of 51 : IPriceImpactUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IPriceImpact.sol";
import "../types/ITradingStorage.sol";

/**
 * @dev Interface for GNSPriceImpact facet (inherits types and also contains functions, events, and custom errors)
 */
interface IPriceImpactUtils is IPriceImpact {
    /**
     * @dev Initializes price impact facet
     * @param _windowsDuration windows duration (seconds)
     * @param _windowsCount windows count
     */
    function initializePriceImpact(uint48 _windowsDuration, uint48 _windowsCount) external;

    /**
     * @dev Initializes negative pnl cumulative volume multiplier
     * @param _negPnlCumulVolMultiplier new value (1e10)
     */
    function initializeNegPnlCumulVolMultiplier(uint40 _negPnlCumulVolMultiplier) external;

    /**
     * @dev Initializes pair factors
     * @param _pairIndices pair indices to initialize
     * @param _protectionCloseFactors protection close factors (1e10)
     * @param _protectionCloseFactorBlocks protection close factor blocks
     * @param _cumulativeFactors cumulative factors (1e10)
     */
    function initializePairFactors(
        uint16[] calldata _pairIndices,
        uint40[] calldata _protectionCloseFactors,
        uint32[] calldata _protectionCloseFactorBlocks,
        uint40[] calldata _cumulativeFactors
    ) external;

    /**
     * @dev Initializes depth bands mapping for price impact calculation
     * @param _slot1 slot 1
     * @param _slot2 slot 2
     */
    function initializeDepthBandsMapping(uint256 _slot1, uint256 _slot2) external;

    /**
     * @dev Updates price impact windows count
     * @param _newWindowsCount new windows count
     */
    function setPriceImpactWindowsCount(uint48 _newWindowsCount) external;

    /**
     * @dev Updates price impact windows duration
     * @param _newWindowsDuration new windows duration (seconds)
     */
    function setPriceImpactWindowsDuration(uint48 _newWindowsDuration) external;

    /**
     * @dev Updates negative pnl cumulative volume multiplier
     * @param _negPnlCumulVolMultiplier new value (1e10)
     */
    function setNegPnlCumulVolMultiplier(uint40 _negPnlCumulVolMultiplier) external;

    /**
     * @dev Whitelists/unwhitelists traders from protection close factor
     * @param _traders traders addresses
     * @param _whitelisted values
     */
    function setProtectionCloseFactorWhitelist(address[] calldata _traders, bool[] calldata _whitelisted) external;

    /**
     * @dev Updates traders price impact settings for pairs
     * @param _traders traders addresses
     * @param _pairIndices pair indices
     * @param _cumulVolPriceImpactMultipliers cumulative volume price impact multipliers (1e3)
     * @param _fixedSpreadPs fixed spreads (1e3 %)
     */
    function setUserPriceImpact(
        address[] calldata _traders,
        uint16[] calldata _pairIndices,
        uint16[] calldata _cumulVolPriceImpactMultipliers,
        uint16[] calldata _fixedSpreadPs
    ) external;

    /**
     * @dev Sets encoded depth bands for price impact calculation per trading pair.
     * See `PairDepthBands` struct for layout.
     * @param _indices Array of pair indices.
     * @param _depthBands Array of PairDepthBands structs with above/below slot encoding.
     */
    function setPairDepthBands(
        uint256[] calldata _indices,
        IPriceImpact.PairDepthBands[] calldata _depthBands
    ) external;

    /**
     * @dev Sets the global depth band offset mapping.
     * See `DepthBandsMapping` struct for layout.
     * @param _slot1 Encoded offsets for bands 0–13 (first 32 bits unused).
     * @param _slot2 Encoded offsets for bands 14–29.
     */
    function setDepthBandsMapping(uint256 _slot1, uint256 _slot2) external;

    /**
     * @dev Updates pairs 1% depths above and below (for skew price impact)
     * @dev Has to be manually updated from time to time based on desired speed of arbitrage (not too often to not cause imbalances)
     * @param _collateralIndices indices of collaterals
     * @param _pairIndices indices of pairs
     * @param _depths depths in tokens (1e18, 0 = no price impact)
     */
    function setPairSkewDepths(
        uint8[] calldata _collateralIndices,
        uint16[] calldata _pairIndices,
        uint256[] calldata _depths
    ) external;

    /**
     * @dev Sets protection close factors for pairs
     * @param _pairIndices pair indices to update
     * @param _protectionCloseFactors new protection close factors (1e10)
     */
    function setProtectionCloseFactors(
        uint16[] calldata _pairIndices,
        uint40[] calldata _protectionCloseFactors
    ) external;

    /**
     * @dev Sets protection close factor blocks duration for pairs
     * @param _pairIndices pair indices to update
     * @param _protectionCloseFactorBlocks new protection close factor blocks
     */
    function setProtectionCloseFactorBlocks(
        uint16[] calldata _pairIndices,
        uint32[] calldata _protectionCloseFactorBlocks
    ) external;

    /**
     * @dev Sets cumulative factors for pairs
     * @param _pairIndices pair indices to update
     * @param _cumulativeFactors new cumulative factors (1e10)
     */
    function setCumulativeFactors(uint16[] calldata _pairIndices, uint40[] calldata _cumulativeFactors) external;

    /**
     * @dev Sets whether pairs are exempt from price impact on open
     * @param _pairIndices pair indices to update
     * @param _exemptOnOpen new values
     */
    function setExemptOnOpen(uint16[] calldata _pairIndices, bool[] calldata _exemptOnOpen) external;

    /**
     * @dev Sets whether pairs are exempt from price impact on close once protection close factor has expired
     * @param _pairIndices pair indices to update
     * @param _exemptAfterProtectionCloseFactor new values
     */
    function setExemptAfterProtectionCloseFactor(
        uint16[] calldata _pairIndices,
        bool[] calldata _exemptAfterProtectionCloseFactor
    ) external;

    /**
     * @dev Adds open interest to current window
     * @param _trader trader address
     * @param _index trade index
     * @param _oiDeltaCollateral open interest to add (collateral precision)
     * @param _open whether it corresponds to opening or closing a trade
     * @param _isPnlPositive whether it corresponds to a positive pnl trade (only relevant when _open = false)
     */
    function addPriceImpactOpenInterest(
        address _trader,
        uint32 _index,
        uint256 _oiDeltaCollateral,
        bool _open,
        bool _isPnlPositive
    ) external;

    /**
     * @dev Updates pair stored open interest after v10
     * @param _collateralIndex index of collateral
     * @param _pairIndex index of pair
     * @param _oiDeltaCollateral open interest delta in collateral tokens (collateral precision)
     * @param _oiDeltaToken open interest delta in tokens (1e18)
     * @param _open whether it corresponds to opening or closing a trade
     * @param _long true for long, false for short
     */
    function updatePairOiAfterV10(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        uint256 _oiDeltaCollateral,
        uint256 _oiDeltaToken,
        bool _open,
        bool _long
    ) external;

    /**
     * @dev Returns active open interest used in price impact calculation for a pair and side (long/short)
     * @param _pairIndex index of pair
     * @param _long true for long, false for short
     */
    function getPriceImpactOi(uint256 _pairIndex, bool _long) external view returns (uint256 activeOi);

    /**
     * @dev Returns cumulative volume price impact % (1e10 precision) for a trade
     * @param _trader trader address (to check if whitelisted from protection close factor)
     * @param _pairIndex index of pair
     * @param _long true for long, false for short
     * @param _tradeOpenInterestUsd open interest of trade in USD (1e18 precision)
     * @param _isPnlPositive true if positive pnl, false if negative pnl (only relevant when _open = false)
     * @param _open true on open, false on close
     * @param _lastPosIncreaseBlock block when trade position size was last increased (only relevant when _open = false)
     */
    function getTradeCumulVolPriceImpactP(
        address _trader,
        uint16 _pairIndex,
        bool _long,
        uint256 _tradeOpenInterestUsd,
        bool _isPnlPositive,
        bool _open,
        uint256 _lastPosIncreaseBlock
    ) external view returns (int256 priceImpactP);

    /**
     * @dev Returns skew price impact % (1e10 precision) for a trade
     * @param _collateralIndex index of collateral
     * @param _pairIndex index of pair
     * @param _long true for long, false for short
     * @param _positionSizeToken open interest of trade in tokens (1e18)
     * @param _open true on open, false on close
     */
    function getTradeSkewPriceImpactP(
        uint8 _collateralIndex,
        uint16 _pairIndex,
        bool _long,
        uint256 _positionSizeToken,
        bool _open
    ) external view returns (int256 priceImpactP);

    /**
     * @dev Returns the encoded depth bands for a specific pair.
     * See `PairDepthBands` struct for layout.
     * @param _pairIndex Pair index.
     * @return Encoded PairDepthBands struct (above and below).
     */
    function getPairDepthBands(uint256 _pairIndex) external view returns (IPriceImpact.PairDepthBands memory);

    /**
     * @dev Returns encoded depth bands for multiple trading pairs.
     * See `PairDepthBands` struct for layout.
     * @param _indices Array of pair indices.
     * @return Array of PairDepthBands structs.
     */
    function getPairDepthBandsArray(
        uint256[] calldata _indices
    ) external view returns (IPriceImpact.PairDepthBands[] memory);

    /**
     * @dev Returns the decoded depth bands for a specific pair.
     * @param _pairIndex Pair index.
     * @return totalDepthAboveUsd total depth above in USD (1e18).
     * @return totalDepthBelowUsd total depth below in USD (1e18).
     * @return bandsAbove above bands liquidity percentages bps (1e2 %).
     * @return bandsBelow below bands liquidity percentages bps (1e2 %).
     */
    function getPairDepthBandsDecoded(
        uint256 _pairIndex
    )
        external
        view
        returns (
            uint256 totalDepthAboveUsd,
            uint256 totalDepthBelowUsd,
            uint16[] memory bandsAbove,
            uint16[] memory bandsBelow
        );

    /**
     * @dev Returns the decoded depth bands for multiple pairs.
     * @param _indices Array of pair indices.
     * @return totalDepthAboveUsd Array of total depth above in USD (1e18).
     * @return totalDepthBelowUsd Array of total depth below in USD (1e18).
     * @return bandsAbove Array of above bands liquidity percentages bps (1e2 %).
     * @return bandsBelow Array of below bands liquidity percentages bps (1e2 %).
     */
    function getPairDepthBandsDecodedArray(
        uint256[] calldata _indices
    )
        external
        view
        returns (
            uint256[] memory totalDepthAboveUsd,
            uint256[] memory totalDepthBelowUsd,
            uint16[][] memory bandsAbove,
            uint16[][] memory bandsBelow
        );

    /**
     * @dev Returns the global depth band offset mapping.
     * See `DepthBandsMapping` struct for layout.
     * @return slot1 Encoded offsets for bands 0–13 (first 32 bits unused).
     * @return slot2 Encoded offsets for bands 14–29.
     */
    function getDepthBandsMapping() external view returns (uint256 slot1, uint256 slot2);

    /**
     * @dev Returns the decoded global depth band offset mapping.
     * @return bands Array of offsets in parts per million (1e4 %).
     */
    function getDepthBandsMappingDecoded() external view returns (uint16[] memory bands);

    /**
     * @dev Returns a pair's depths above and below the price (for skew price impact)
     * @param _collateralIndex index of collateral
     * @param _pairIndex index of pair
     */
    function getPairSkewDepth(uint8 _collateralIndex, uint16 _pairIndex) external view returns (uint256);

    /**
     * @dev Returns current price impact windows settings
     */
    function getOiWindowsSettings() external view returns (OiWindowsSettings memory);

    /**
     * @dev Returns OI window details (long/short OI)
     * @param _windowsDuration windows duration (seconds)
     * @param _pairIndex index of pair
     * @param _windowId id of window
     */
    function getOiWindow(
        uint48 _windowsDuration,
        uint256 _pairIndex,
        uint256 _windowId
    ) external view returns (PairOi memory);

    /**
     * @dev Returns multiple OI windows details (long/short OI)
     * @param _windowsDuration windows duration (seconds)
     * @param _pairIndex index of pair
     * @param _windowIds ids of windows
     */
    function getOiWindows(
        uint48 _windowsDuration,
        uint256 _pairIndex,
        uint256[] calldata _windowIds
    ) external view returns (PairOi[] memory);

    /**
     * @dev Returns depths above and below the price for multiple pairs for skew price impact (tokens, 1e18)
     * @param _collateralIndices indices of collaterals
     * @param _pairIndices indices of pairs
     */
    function getPairSkewDepths(
        uint8[] calldata _collateralIndices,
        uint16[] calldata _pairIndices
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns factors for a set of pairs (1e10)
     * @param _indices indices of pairs
     */
    function getPairFactors(uint256[] calldata _indices) external view returns (IPriceImpact.PairFactors[] memory);

    /**
     * @dev Returns negative pnl cumulative volume multiplier
     */
    function getNegPnlCumulVolMultiplier() external view returns (uint48);

    /**
     * @dev Returns whether a trader is whitelisted from protection close factor
     * @param _trader trader address
     */
    function getProtectionCloseFactorWhitelist(address _trader) external view returns (bool);

    /**
     * @dev Returns a trader's price impact settings on a particular pair
     * @param _trader trader address
     * @param _pairIndex pair index
     */
    function getUserPriceImpact(
        address _trader,
        uint256 _pairIndex
    ) external view returns (IPriceImpact.UserPriceImpact memory);

    /**
     * @dev Returns a pair's open interest in collateral tokens after v10 (collateral precision)
     * @param _collateralIndex collateral index
     * @param _pairIndex pair index
     */
    function getPairOiAfterV10Collateral(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (IPriceImpact.PairOiCollateral memory);

    /**
     * @dev Returns multiple pairs' open interests in collateral tokens after v10 (collateral precision)
     * @param _collateralIndex collateral indices
     * @param _pairIndex pair indices
     */
    function getPairOisAfterV10Collateral(
        uint8[] memory _collateralIndex,
        uint16[] memory _pairIndex
    ) external view returns (IPriceImpact.PairOiCollateral[] memory);

    /**
     * @dev Returns a pair's open interest in tokens after v10 (1e18)
     * @param _collateralIndex collateral index
     * @param _pairIndex pair index
     */
    function getPairOiAfterV10Token(
        uint8 _collateralIndex,
        uint16 _pairIndex
    ) external view returns (IPriceImpact.PairOiToken memory);

    /**
     * @dev Returns multiple pairs' open interests in tokens after v10 (collateral precision)
     * @param _collateralIndex collateral indices
     * @param _pairIndex pair indices
     */
    function getPairOisAfterV10Token(
        uint8[] memory _collateralIndex,
        uint16[] memory _pairIndex
    ) external view returns (IPriceImpact.PairOiToken[] memory);

    /**
     * @dev Triggered when OiWindowsSettings is initialized (once)
     * @param windowsDuration duration of each window (seconds)
     * @param windowsCount number of windows
     */
    event OiWindowsSettingsInitialized(uint48 indexed windowsDuration, uint48 indexed windowsCount);

    /**
     * @dev Triggered when OiWindowsSettings.windowsCount is updated
     * @param windowsCount new number of windows
     */
    event PriceImpactWindowsCountUpdated(uint48 indexed windowsCount);

    /**
     * @dev Triggered when OiWindowsSettings.windowsDuration is updated
     * @param windowsDuration new duration of each window (seconds)
     */
    event PriceImpactWindowsDurationUpdated(uint48 indexed windowsDuration);

    /**
     * @dev Triggered when negPnlCumulVolMultiplier is updated
     * @param negPnlCumulVolMultiplier new value (1e10)
     */
    event NegPnlCumulVolMultiplierUpdated(uint40 indexed negPnlCumulVolMultiplier);

    /**
     * @dev Triggered when a trader is whitelisted/unwhitelisted from protection close factor
     * @param trader trader address
     * @param whitelisted true if whitelisted, false if unwhitelisted
     */
    event ProtectionCloseFactorWhitelistUpdated(address trader, bool whitelisted);

    /**
     * @dev Triggered when a trader's price impact data is updated
     * @param trader trader address
     * @param pairIndex pair index
     * @param cumulVolPriceImpactMultiplier cumulative volume price impact multiplier (1e3)
     * @param fixedSpreadP fixed spread (1e3 %)
     */
    event UserPriceImpactUpdated(
        address indexed trader,
        uint16 indexed pairIndex,
        uint16 cumulVolPriceImpactMultiplier,
        uint16 fixedSpreadP
    );

    /**
     * @dev Triggered when a pair's protection close factor is updated
     * @param pairIndex index of the pair
     * @param protectionCloseFactor new protection close factor (1e10)
     */
    event ProtectionCloseFactorUpdated(uint256 indexed pairIndex, uint40 protectionCloseFactor);

    /**
     * @dev Triggered when a pair's protection close factor duration is updated
     * @param pairIndex index of the pair
     * @param protectionCloseFactorBlocks new protection close factor blocks
     */
    event ProtectionCloseFactorBlocksUpdated(uint256 indexed pairIndex, uint32 protectionCloseFactorBlocks);

    /**
     * @dev Triggered when a pair's cumulative factor is updated
     * @param pairIndex index of the pair
     * @param cumulativeFactor new cumulative factor (1e10)
     */
    event CumulativeFactorUpdated(uint256 indexed pairIndex, uint40 cumulativeFactor);

    /**
     * @dev Triggered when a pair's exemptOnOpen value is updated
     * @param pairIndex index of the pair
     * @param exemptOnOpen whether the pair is exempt of price impact on open
     */
    event ExemptOnOpenUpdated(uint256 indexed pairIndex, bool exemptOnOpen);

    /**
     * @dev Triggered when a pair's exemptAfterProtectionCloseFactor value is updated
     * @param pairIndex index of the pair
     * @param exemptAfterProtectionCloseFactor whether the pair is exempt of price impact on close once protection close factor has expired
     */
    event ExemptAfterProtectionCloseFactorUpdated(uint256 indexed pairIndex, bool exemptAfterProtectionCloseFactor);

    /**
     * @dev Triggered when OI is added to a window.
     * @param oiWindowUpdate OI window update details (windowsDuration, pairIndex, windowId, etc.)
     */
    event PriceImpactOpenInterestAdded(IPriceImpact.OiWindowUpdate oiWindowUpdate);

    /**
     * @dev Triggered when a pair's OI after v10 is updated.
     * @param collateralIndex index of collateral
     * @param pairIndex index of pair
     * @param oiDeltaCollateral open interest delta in collateral tokens (collateral precision)
     * @param oiDeltaToken open interest delta in tokens (1e18)
     * @param open whether it corresponds to opening or closing a trade
     * @param long true for long, false for short
     * @param newOiCollateral new OI collateral after v10 (collateral precision)
     * @param newOiToken new OI token after v10 (1e18)
     */
    event PairOiAfterV10Updated(
        uint8 indexed collateralIndex,
        uint16 indexed pairIndex,
        uint256 oiDeltaCollateral,
        uint256 oiDeltaToken,
        bool open,
        bool long,
        IPriceImpact.PairOiCollateral newOiCollateral,
        IPriceImpact.PairOiToken newOiToken
    );

    /**
     * @dev Triggered when multiple pairs' OI are transferred to a new window (when updating windows duration).
     * @param pairsCount number of pairs
     * @param prevCurrentWindowId previous current window ID corresponding to previous window duration
     * @param prevEarliestWindowId previous earliest window ID corresponding to previous window duration
     * @param newCurrentWindowId new current window ID corresponding to new window duration
     */
    event PriceImpactOiTransferredPairs(
        uint256 pairsCount,
        uint256 prevCurrentWindowId,
        uint256 prevEarliestWindowId,
        uint256 newCurrentWindowId
    );

    /**
     * @dev Triggered when a pair's OI is transferred to a new window.
     * @param pairIndex index of the pair
     * @param totalPairOi total USD long/short OI of the pair (1e18 precision)
     */
    event PriceImpactOiTransferredPair(uint256 indexed pairIndex, IPriceImpact.PairOi totalPairOi);

    /**
     * @dev Triggered when a pair's 1% depth is updated (for cumulative volume price impact).
     * @param pairIndex index of the pair
     * @param valueAboveUsd new USD depth above the price
     * @param valueBelowUsd new USD depth below the price
     */
    event OnePercentDepthUpdated(uint256 indexed pairIndex, uint128 valueAboveUsd, uint128 valueBelowUsd);

    /**
     * @dev Triggered when a pair's 1% depth is updated (for skew price impact).
     * @param pairIndex index of the pair
     * @param newValue new depth above/below the price (1e18, token)
     */
    event OnePercentSkewDepthUpdated(uint8 indexed collateralIndex, uint16 indexed pairIndex, uint256 newValue);

    /**
     * @dev Triggered when a pair's depth bands are updated.
     * @param pairIndex index of the pair
     * @param aboveSlot1 first slot for above bands (totalDepthUsd + 14 bands)
     * @param aboveSlot2 second slot for above bands (16 bands)
     * @param belowSlot1 first slot for below bands (totalDepthUsd + 14 bands)
     * @param belowSlot2 second slot for below bands (16 bands)
     */
    event PairDepthBandsUpdated(
        uint256 indexed pairIndex,
        uint256 aboveSlot1,
        uint256 aboveSlot2,
        uint256 belowSlot1,
        uint256 belowSlot2
    );

    /**
     * @dev Emitted when depth bands mapping is updated
     * @param slot1 Slot 1 data containing the first 14 bands offsets
     * @param slot2 Slot 2 data containing the last 16 bands offsets
     */
    event DepthBandsMappingUpdated(uint256 slot1, uint256 slot2);

    error WrongWindowsDuration();
    error WrongWindowsCount();
    error WrongDepthBandsOrder();
    error DepthBandsAboveMax();
    error DepthBandsIncomplete();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IReferrals.sol";

/**
 * @dev Interface for GNSReferrals facet (inherits types and also contains functions, events, and custom errors)
 */
interface IReferralsUtils is IReferrals {
    /**
     *
     * @param _allyFeeP % of total referral fee going to ally
     * @param _startReferrerFeeP initial % of total referral fee earned when zero volume referred
     * @param _targetVolumeUsd usd opening volume to refer to reach 100% of referral fee
     */
    function initializeReferrals(uint256 _allyFeeP, uint256 _startReferrerFeeP, uint256 _targetVolumeUsd) external;

    /**
     * @dev Updates allyFeeP
     * @param _value new ally fee %
     */
    function updateAllyFeeP(uint256 _value) external;

    /**
     * @dev Updates startReferrerFeeP
     * @param _value new start referrer fee %
     */
    function updateStartReferrerFeeP(uint256 _value) external;

    /**
     * @dev Updates targetVolumeUsd
     * @param _value new target volume in usd
     */
    function updateReferralsTargetVolumeUsd(uint256 _value) external;

    /**
     * @dev Whitelists ally addresses
     * @param _allies array of ally addresses
     */
    function whitelistAllies(address[] calldata _allies) external;

    /**
     * @dev Unwhitelists ally addresses
     * @param _allies array of ally addresses
     */
    function unwhitelistAllies(address[] calldata _allies) external;

    /**
     * @dev Whitelists referrer addresses
     * @param _referrers array of referrer addresses
     * @param _allies array of corresponding ally addresses
     */
    function whitelistReferrers(address[] calldata _referrers, address[] calldata _allies) external;

    /**
     * @dev Unwhitelists referrer addresses
     * @param _referrers array of referrer addresses
     */
    function unwhitelistReferrers(address[] calldata _referrers) external;

    /**
     * @dev Overrides referral fee % share of total trading fee for referrers
     * @param _referrers array of referrer addresses
     * @param _referralFeeP array of referral fee % (1e3)
     */
    function overrideReferralFeeP(address[] calldata _referrers, uint24[] calldata _referralFeeP) external;

    /**
     * @dev Overrides ally fee % share of total trading fee for allies
     * @param _allies array of ally addresses
     * @param _allyFeeP array of ally fee % (1e3)
     */
    function overrideAllyFeeP(address[] calldata _allies, uint24[] calldata _allyFeeP) external;

    /**
     * @dev Registers potential referrer for trader (only works if trader wasn't referred yet by someone else)
     * @param _trader trader address
     * @param _referral referrer address
     */
    function registerPotentialReferrer(address _trader, address _referral) external;

    /**
     * @dev Distributes ally and referrer rewards
     * @param _trader trader address
     * @param _volumeUsd trading volume in usd (1e18 precision)
     * @param _referrerFeeUsd referrer fee in USD (1e18 precision)
     * @param _gnsPriceUsd token price in usd (1e10 precision)
     */
    function distributeReferralReward(
        address _trader,
        uint256 _volumeUsd, // 1e18
        uint256 _referrerFeeUsd,
        uint256 _gnsPriceUsd // 1e10
    ) external;

    /**
     * @dev Claims pending GNS ally rewards of caller
     */
    function claimAllyRewards() external;

    /**
     * @dev Claims pending GNS referrer rewards of caller
     */
    function claimReferrerRewards() external;

    /**
     * @dev Returns referrer fee % progress towards earning 100% based on his volume referred (1e10)
     * @param _referrer referrer address
     */
    function getReferrerFeeProgressP(address _referrer) external view returns (uint256);

    /**
     * @dev Returns last referrer of trader (whether referrer active or not)
     * @param _trader address of trader
     */
    function getTraderLastReferrer(address _trader) external view returns (address);

    /**
     * @dev Returns active referrer of trader
     * @param _trader address of trader
     */
    function getTraderActiveReferrer(address _trader) external view returns (address);

    /**
     * @dev Returns referrers referred by ally
     * @param _ally address of ally
     */
    function getReferrersReferred(address _ally) external view returns (address[] memory);

    /**
     * @dev Returns traders referred by referrer
     * @param _referrer address of referrer
     */
    function getTradersReferred(address _referrer) external view returns (address[] memory);

    /**
     * @dev Returns ally fee % of total referral fee
     */
    function getReferralsAllyFeeP() external view returns (uint256);

    /**
     * @dev Returns start referrer fee % of total referral fee when zero volume was referred
     */
    function getReferralsStartReferrerFeeP() external view returns (uint256);

    /**
     * @dev Returns target volume in usd to reach 100% of referral fee
     */
    function getReferralsTargetVolumeUsd() external view returns (uint256);

    /**
     * @dev Returns ally details
     * @param _ally address of ally
     */
    function getAllyDetails(address _ally) external view returns (AllyDetails memory);

    /**
     * @dev Returns referrer details
     * @param _referrer address of referrer
     */
    function getReferrerDetails(address _referrer) external view returns (ReferrerDetails memory);

    /**
     * @dev Returns referral settings overrides
     * @param _address address of referrer/ally
     */
    function getReferralSettingsOverrides(address _address) external view returns (ReferralSettingsOverrides memory);

    /**
     * @dev Emitted when allyFeeP is updated
     * @param value new ally fee %
     */
    event UpdatedAllyFeeP(uint256 value);

    /**
     * @dev Emitted when startReferrerFeeP is updated
     * @param value new start referrer fee %
     */
    event UpdatedStartReferrerFeeP(uint256 value);

    /**
     * @dev Emitted when openFeeP is updated
     * @param value new open fee %
     */
    event UpdatedOpenFeeP(uint256 value);

    /**
     * @dev Emitted when targetVolumeUsd is updated
     * @param value new target volume in usd
     */
    event UpdatedTargetVolumeUsd(uint256 value);

    /**
     * @dev Emitted when an ally is whitelisted
     * @param ally ally address
     */
    event AllyWhitelisted(address indexed ally);

    /**
     * @dev Emitted when an ally is unwhitelisted
     * @param ally ally address
     */
    event AllyUnwhitelisted(address indexed ally);

    /**
     * @dev Emitted when a referrer is whitelisted
     * @param referrer referrer address
     * @param ally ally address
     */
    event ReferrerWhitelisted(address indexed referrer, address indexed ally);

    /**
     * @dev Emitted when a referrer is unwhitelisted
     * @param referrer referrer address
     */
    event ReferrerUnwhitelisted(address indexed referrer);

    /**
     * @dev Emitted when a trader has a new active referrer
     */
    event ReferrerRegistered(address indexed trader, address indexed referrer);

    /**
     * @dev Emitted when ally rewards are distributed for a trade
     * @param ally address of ally
     * @param trader address of trader
     * @param volumeUsd trade volume in usd (1e18 precision)
     * @param amountGns amount of GNS reward (1e18 precision)
     * @param amountValueUsd USD value of GNS reward (1e18 precision)
     */
    event AllyRewardDistributed(
        address indexed ally,
        address indexed trader,
        uint256 volumeUsd,
        uint256 amountGns,
        uint256 amountValueUsd
    );

    /**
     * @dev Emitted when referrer rewards are distributed for a trade
     * @param referrer address of referrer
     * @param trader address of trader
     * @param volumeUsd trade volume in usd (1e18 precision)
     * @param amountGns amount of GNS reward (1e18 precision)
     * @param amountValueUsd USD value of GNS reward (1e18 precision)
     */
    event ReferrerRewardDistributed(
        address indexed referrer,
        address indexed trader,
        uint256 volumeUsd,
        uint256 amountGns,
        uint256 amountValueUsd
    );

    /**
     * @dev Emitted when an ally claims his pending rewards
     * @param ally address of ally
     * @param amountGns GNS pending rewards amount
     */
    event AllyRewardsClaimed(address indexed ally, uint256 amountGns);

    /**
     * @dev Emitted when a referrer claims his pending rewards
     * @param referrer address of referrer
     * @param amountGns GNS pending rewards amount
     */
    event ReferrerRewardsClaimed(address indexed referrer, uint256 amountGns);

    /**
     * @dev Emitted when a referrer fee % is overridden
     * @param referrer referrer address
     * @param referralFeeP new referral fee % (1e3)
     */
    event OverrodeReferralFeeP(address indexed referrer, uint24 referralFeeP);

    /**
     * @dev Emitted when an ally fee % is overridden
     * @param ally ally address
     * @param allyFeeP new ally fee % (1e3)
     */
    event OverrodeAllyFeeP(address indexed ally, uint24 allyFeeP);

    error NoPendingRewards();
    error AlreadyActive();
    error AlreadyInactive();
    error AllyNotActive();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITradingCallbacks.sol";
import "../libraries/IUpdateLeverageUtils.sol";
import "../libraries/IUpdatePositionSizeUtils.sol";
import "../libraries/ITradingCommonUtils.sol";

/**
 * @dev Interface for GNSTradingCallbacks facet (inherits types and also contains functions, events, and custom errors)
 */
interface ITradingCallbacksUtils is
    ITradingCallbacks,
    IUpdateLeverageUtils,
    IUpdatePositionSizeUtils,
    ITradingCommonUtils
{
    /**
     *
     * @param _vaultClosingFeeP the % of closing fee going to vault
     */
    function initializeCallbacks(uint8 _vaultClosingFeeP) external;

    /**
     * @dev Initialize the treasury address
     * @param _treasury the treasury address
     */
    function initializeTreasuryAddress(address _treasury) external;

    /**
     * @dev Update the % of closing fee going to vault
     * @param _valueP the % of closing fee going to vault
     */
    function updateVaultClosingFeeP(uint8 _valueP) external;

    /**
     * @dev Updates the treasury address
     * @param _treasury the new treasury address
     */
    function updateTreasuryAddress(address _treasury) external;

    /**
     * @dev Claim the pending gov fees for all collaterals
     */
    function claimPendingGovFees() external;

    /**
     * @dev Executes a pending open trade market order
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function openTradeMarketCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending close trade market order
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function closeTradeMarketCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending open trigger order (for limit/stop orders)
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function executeTriggerOpenOrderCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes open trigger directly (for limit/stop orders)
     * @param _a the price aggregator answer (order id, price, etc.)
     * @param _trade the trade object to execute the trigger for
     * @param _orderType the pending order type
     * @param _initiator the address that initiated the trigger execution
     */
    function executeTriggerOpenOrderCallbackDirect(
        ITradingCallbacks.AggregatorAnswer memory _a,
        ITradingStorage.Trade memory _trade,
        ITradingStorage.PendingOrderType _orderType,
        address _initiator
    ) external;

    /**
     * @dev Executes a pending close trigger order (for tp/sl/liq orders)
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function executeTriggerCloseOrderCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes close trigger directly (for tp/sl/liq orders)
     * @param _a the price aggregator answer (order id, price, etc.)
     * @param _trade the trade object to execute the trigger for
     * @param _orderType the pending order type
     * @param _initiator the address that initiated the trigger execution
     */
    function executeTriggerCloseOrderCallbackDirect(
        ITradingCallbacks.AggregatorAnswer memory _a,
        ITradingStorage.Trade memory _trade,
        ITradingStorage.PendingOrderType _orderType,
        address _initiator
    ) external;

    /**
     * @dev Executes a pending update leverage order
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function updateLeverageCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending increase position size market order
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function increasePositionSizeMarketCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending decrease position size market order
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function decreasePositionSizeMarketCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending pnl withdrawal
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function pnlWithdrawalCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending holding fees realization
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function manualHoldingFeesRealizationCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Executes a pending negative pnl realization
     * @param _a the price aggregator answer (order id, price, etc.)
     */
    function manualNegativePnlRealizationCallback(AggregatorAnswer memory _a) external;

    /**
     * @dev Returns the current vaultClosingFeeP value (%)
     */
    function getVaultClosingFeeP() external view returns (uint8);

    /**
     * @dev Returns the current pending gov fees for a collateral index (collateral precision)
     */
    function getPendingGovFeesCollateral(uint8 _collateralIndex) external view returns (uint256);

    /**
     * @dev Makes open trigger (STOP/LIMIT) checks like slippage, price impact, missed targets and returns cancellation reason if any
     * @param _tradeId the id of the trade
     * @param _orderType the pending order type
     * @param _open the open value of the candle to check (1e10)
     * @param _high the high value of the candle to check (1e10)
     * @param _low the low value of the candle to check (1e10)
     * @param _currentPairPrice the current pair price (1e10)
     */
    function validateTriggerOpenOrderCallback(
        ITradingStorage.Id memory _tradeId,
        ITradingStorage.PendingOrderType _orderType,
        uint64 _open,
        uint64 _high,
        uint64 _low,
        uint64 _currentPairPrice
    ) external view returns (ITradingStorage.Trade memory t, ITradingCallbacks.Values memory v);

    /**
     * @dev Makes close trigger (SL/TP/LIQ) checks like slippage and price impact and returns cancellation reason if any
     * @param _tradeId the id of the trade
     * @param _orderType the pending order type
     * @param _open the open value of the candle to check (1e10)
     * @param _high the high value of the candle to check (1e10)
     * @param _low the low value of the candle to check (1e10)
     * @param _currentPairPrice the current pair price (1e10)
     */
    function validateTriggerCloseOrderCallback(
        ITradingStorage.Id memory _tradeId,
        ITradingStorage.PendingOrderType _orderType,
        uint64 _open,
        uint64 _high,
        uint64 _low,
        uint64 _currentPairPrice
    ) external view returns (ITradingStorage.Trade memory t, ITradingCallbacks.Values memory v);

    /**
     * @dev Emitted when vaultClosingFeeP is updated
     * @param valueP the % of closing fee going to vault
     */
    event VaultClosingFeePUpdated(uint8 valueP);

    /**
     * @dev Emitted when gov fees are claimed for a collateral
     * @param collateralIndex the collateral index
     * @param amountCollateral the amount of fees claimed (collateral precision)
     */
    event PendingGovFeesClaimed(uint8 collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when a market order is executed (open/close)
     * @param orderId the id of the corresponding pending market order
     * @param user trade user
     * @param index trade index
     * @param t the trade object
     * @param open true for a market open order, false for a market close order
     * @param oraclePrice the oracle price without spread/impact (1e10 precision)
     * @param marketPrice the price at which the trade was executed (1e10 precision)
     * @param liqPrice trade liquidation price (1e10 precision)
     * @param priceImpact price impact details
     * @param percentProfit the profit in percentage (1e10 precision)
     * @param amountSentToTrader the final amount of collateral sent to the trader
     * @param collateralPriceUsd the price of the collateral in USD (1e8 precision)
     */
    event MarketExecuted(
        ITradingStorage.Id orderId,
        address indexed user,
        uint32 indexed index,
        ITradingStorage.Trade t,
        bool open,
        uint256 oraclePrice,
        uint256 marketPrice,
        uint256 liqPrice,
        ITradingCommonUtils.TradePriceImpact priceImpact,
        int256 percentProfit, // before fees
        uint256 amountSentToTrader,
        uint256 collateralPriceUsd // 1e8
    );

    /**
     * @dev Emitted when a limit/stop order is executed
     * @param orderId the id of the corresponding pending trigger order
     * @param user trade user
     * @param index trade index
     * @param limitIndex limit index
     * @param t the trade object
     * @param triggerCaller the address that triggered the limit order
     * @param orderType the type of the pending order
     * @param oraclePrice the oracle price without spread/impact (1e10 precision)
     * @param marketPrice the price at which the trade was executed (1e10 precision)
     * @param liqPrice trade liquidation price (1e10 precision)
     * @param priceImpact price impact details
     * @param percentProfit the profit in percentage (1e10 precision)
     * @param amountSentToTrader the final amount of collateral sent to the trader
     * @param collateralPriceUsd the price of the collateral in USD (1e8 precision)
     * @param exactExecution true if guaranteed execution was used
     */
    event LimitExecuted(
        ITradingStorage.Id orderId,
        address indexed user,
        uint32 indexed index,
        uint32 indexed limitIndex,
        ITradingStorage.Trade t,
        address triggerCaller,
        ITradingStorage.PendingOrderType orderType,
        uint256 oraclePrice,
        uint256 marketPrice,
        uint256 liqPrice,
        ITradingCommonUtils.TradePriceImpact priceImpact,
        int256 percentProfit,
        uint256 amountSentToTrader,
        uint256 collateralPriceUsd, // 1e8
        bool exactExecution
    );

    /**
     * @dev Emitted when a pending market open order is canceled
     * @param orderId order id of the pending market open order
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param cancelReason reason for the cancellation
     * @param collateralReturned collateral returned to trader (collateral precision)
     */
    event MarketOpenCanceled(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint256 indexed pairIndex,
        CancelReason cancelReason,
        uint256 collateralReturned
    );

    /**
     * @dev Emitted when a pending market close order is canceled
     * @param orderId order id of the pending market close order
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param index index of the trade for trader
     * @param cancelReason reason for the cancellation
     */
    event MarketCloseCanceled(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint256 indexed pairIndex,
        uint256 indexed index,
        CancelReason cancelReason
    );

    /**
     * @dev Emitted when a pending trigger order is canceled
     * @param orderId order id of the pending trigger order
     * @param triggerCaller address of the trigger caller
     * @param orderType type of the pending trigger order
     * @param cancelReason reason for the cancellation
     */
    event TriggerOrderCanceled(
        ITradingStorage.Id orderId,
        address indexed triggerCaller,
        ITradingStorage.PendingOrderType orderType,
        CancelReason cancelReason
    );

    /**
     * @dev Emitted when a trade's holding fees are manually realized
     * @param orderId corresponding order id
     * @param collateralIndex collateral index
     * @param trader address of the trader
     * @param index index of the trade
     * @param currentPairPrice current pair price (1e10 precision)
     */
    event TradeHoldingFeesManuallyRealized(
        ITradingStorage.Id orderId,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        uint256 currentPairPrice
    );

    /**
     * @dev Emitted when positive pnl is claimed on an open trade
     * @param orderId corresponding order id
     * @param collateralIndex collateral index
     * @param trader address of the trader
     * @param index index of the trade
     * @param priceImpact closing price impact details
     * @param pnlPercent raw trade pnl percent (1e10 precision)
     * @param withdrawablePositivePnlCollateral maximum withdrawable positive pnl in collateral tokens (collateral precision)
     * @param currentPairPrice current pair price (1e10 precision)
     * @param pnlInputCollateral input for amount of positive pnl to withdraw (collateral precision)
     * @param pnlWithdrawnCollateral final positive pnl withdrawn in collateral tokens (collateral precision)
     */
    event TradePositivePnlWithdrawn(
        ITradingStorage.Id orderId,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        ITradingCommonUtils.TradePriceImpact priceImpact,
        int256 pnlPercent,
        int256 withdrawablePositivePnlCollateral,
        uint256 currentPairPrice,
        uint256 pnlInputCollateral,
        uint256 pnlWithdrawnCollateral
    );

    /**
     * @dev Emitted when a trade's negative pnl is manually realized
     * @param orderId corresponding order id
     * @param collateralIndex collateral index
     * @param trader address of the trader
     * @param index index of the trade
     * @param negativePnlCollateral current negative pnl in collateral tokens (collateral precision)
     * @param existingManuallyRealizedNegativePnlCollateral existing manually realized negative pnl in collateral tokens (collateral precision)
     * @param newManuallyRealizedNegativePnlCollateral new manually realized negative pnl in collateral tokens (collateral precision)
     * @param currentPairPrice current pair price (1e10 precision)
     */
    event TradeNegativePnlManuallyRealized(
        ITradingStorage.Id orderId,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        uint256 negativePnlCollateral,
        uint256 existingManuallyRealizedNegativePnlCollateral,
        uint256 newManuallyRealizedNegativePnlCollateral,
        uint256 currentPairPrice
    );

    /**
     * @dev Emitted when excess counter trade collateral is returned to trader
     * @param orderId corresponding order id
     * @param collateralIndex collateral index
     * @param trader trader address
     * @param collateralReturned collateral amount returned to trader (collateral precision)
     */
    event CounterTradeCollateralReturned(
        ITradingStorage.Id orderId,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 collateralReturned
    );

    error PendingOrderNotOpen();
}

File 28 of 51 : ITradingCommonUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITradingStorage.sol";

/**
 * @dev Interface for TradingCommonUtils library
 */
interface ITradingCommonUtils {
    struct TradePriceImpactInput {
        ITradingStorage.Trade trade;
        uint256 oraclePrice; // 1e10
        uint256 positionSizeCollateral; // collateral precision
        uint64 currentPairPrice; // 1e10
        bool useCumulativeVolPriceImpact;
    }

    struct TradePriceImpact {
        uint256 positionSizeToken; // 1e18
        int256 fixedSpreadP; // 1e10 (%)
        int256 cumulVolPriceImpactP; // 1e10 (%)
        int256 skewPriceImpactP; // 1e10 (%)
        int256 totalPriceImpactP; // 1e10 (%)
        uint64 priceAfterImpact; // 1e10
    }

    /**
     * @dev Emitted when gov fee is charged
     * @param trader address of the trader
     * @param collateralIndex index of the collateral
     * @param amountCollateral amount charged (collateral precision)
     */
    event GovFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when referral fee is charged
     * @param trader address of the trader
     * @param collateralIndex index of the collateral
     * @param amountCollateral amount charged (collateral precision)
     */
    event ReferralFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when GNS otc fee is charged
     * @param trader address of the trader
     * @param collateralIndex index of the collateral
     * @param amountCollateral amount charged (collateral precision)
     */
    event GnsOtcFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when trigger fee is charged
     * @param trader address of the trader
     * @param collateralIndex index of the collateral
     * @param amountCollateral amount charged (collateral precision)
     */
    event TriggerFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when gToken fee is charged
     * @param trader address of the trader
     * @param collateralIndex index of the collateral
     * @param amountCollateral amount charged (collateral precision)
     */
    event GTokenFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral);

    /**
     * @dev Emitted when a trade's fees are processed
     * @param collateralIndex index of the collateral
     * @param trader address of the trader
     * @param positionSizeCollateral position size (collateral precision)
     * @param orderType type of the order
     * @param totalFeesCollateral amount of fees charged (collateral precision)
     */
    event FeesProcessed(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 positionSizeCollateral,
        ITradingStorage.PendingOrderType orderType,
        uint256 totalFeesCollateral
    );

    /**
     * @dev Emitted when a trade's value is transferred
     * @param collateralIndex index of the collateral
     * @param trader address of the trader
     * @param index index of the trade
     * @param collateralSentToTrader amount of collateral sent to the trader (collateral precision)
     * @param availableCollateralInDiamond amount of available collateral in the diamond (collateral precision)
     */
    event TradeValueTransferred(
        uint8 indexed collateralIndex,
        address indexed trader,
        uint32 indexed index,
        int256 collateralSentToTrader,
        int256 availableCollateralInDiamond
    );
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITradingInteractions.sol";
import "../types/ITradingStorage.sol";
import "../types/IPriceAggregator.sol";
import "../libraries/IUpdateLeverageUtils.sol";
import "../libraries/IUpdatePositionSizeUtils.sol";

/**
 * @dev Interface for GNSTradingInteractions facet (inherits types and also contains functions, events, and custom errors)
 */
interface ITradingInteractionsUtils is ITradingInteractions, IUpdateLeverageUtils, IUpdatePositionSizeUtils {
    /**
     * @dev Initializes the trading facet
     * @param _marketOrdersTimeoutBlocks The number of blocks after which a market order is considered timed out
     */
    function initializeTrading(uint16 _marketOrdersTimeoutBlocks, address[] memory _usersByPassTriggerLink) external;

    /**
     * @dev Updates marketOrdersTimeoutBlocks
     * @param _valueBlocks blocks after which a market order times out
     */
    function updateMarketOrdersTimeoutBlocks(uint16 _valueBlocks) external;

    /**
     * @dev Updates the users that can bypass the link cost of triggerOrder
     * @param _users array of addresses that can bypass the link cost of triggerOrder
     * @param _shouldByPass whether each user should bypass the link cost
     */
    function updateByPassTriggerLink(address[] memory _users, bool[] memory _shouldByPass) external;

    /**
     * @dev Initiates manual holding fees / negative pnl realization for an open trade (sends negative pnl into vault to avoid temporary imbalances due to timing of trades closing)
     * @param _trader trader address
     * @param _index trade index
     * @param _isHoldingFees true if holding fees realization, false if negative pnl realization
     */
    function initiateManualNegativePnlRealization(address _trader, uint32 _index, bool _isHoldingFees) external;

    /**
     * @dev Sets _delegate as the new delegate of caller (can call delegatedAction)
     * @param _delegate the new delegate address
     */
    function setTradingDelegate(address _delegate) external;

    /**
     * @dev Removes the delegate of caller (can't call delegatedAction)
     */
    function removeTradingDelegate() external;

    /**
     * @dev Caller executes a trading action on behalf of _trader using delegatecall
     * @param _trader the trader address to execute the trading action for
     * @param _callData the data to be executed (open trade/close trade, etc.)
     */
    function delegatedTradingAction(address _trader, bytes calldata _callData) external returns (bytes memory);

    /**
     * @dev Opens a new trade/limit order/stop order
     * @param _trade the trade to be opened
     * @param _maxSlippageP the maximum allowed slippage % when open the trade (1e3 precision)
     * @param _referrer the address of the referrer (can only be set once for a trader)
     */
    function openTrade(ITradingStorage.Trade memory _trade, uint16 _maxSlippageP, address _referrer) external;

    /**
     * @dev Wraps native token and opens a new trade/limit order/stop order
     * @param _trade the trade to be opened
     * @param _maxSlippageP the maximum allowed slippage % when open the trade (1e3 precision)
     * @param _referrer the address of the referrer (can only be set once for a trader)
     */
    function openTradeNative(
        ITradingStorage.Trade memory _trade,
        uint16 _maxSlippageP,
        address _referrer
    ) external payable;

    /**
     * @dev Updates existing trade's max closing slippage % for caller
     * @param _index index of trade
     * @param _maxSlippageP new max closing slippage % (1e3 precision)
     */
    function updateMaxClosingSlippageP(uint32 _index, uint16 _maxSlippageP) external;

    /**
     * @dev Closes an open trade (market order) for caller
     * @param _index the index of the trade of caller
     * @param _expectedPrice expected closing price, used to check max slippage (1e10 precision)
     */
    function closeTradeMarket(uint32 _index, uint64 _expectedPrice) external;

    /**
     * @dev Updates an existing limit/stop order for caller
     * @param _index index of limit/stop order of caller
     * @param _triggerPrice new trigger price of limit/stop order (1e10 precision)
     * @param _tp new tp of limit/stop order (1e10 precision)
     * @param _sl new sl of limit/stop order (1e10 precision)
     * @param _maxSlippageP new max slippage % of limit/stop order (1e3 precision)
     */
    function updateOpenOrder(
        uint32 _index,
        uint64 _triggerPrice,
        uint64 _tp,
        uint64 _sl,
        uint16 _maxSlippageP
    ) external;

    /**
     * @dev Cancels an open limit/stop order for caller
     * @param _index index of limit/stop order of caller
     */
    function cancelOpenOrder(uint32 _index) external;

    /**
     * @dev Updates the tp of an open trade for caller
     * @param _index index of open trade of caller
     * @param _newTp new tp of open trade (1e10 precision)
     */
    function updateTp(uint32 _index, uint64 _newTp) external;

    /**
     * @dev Updates the sl of an open trade for caller
     * @param _index index of open trade of caller
     * @param _newSl new sl of open trade (1e10 precision)
     */
    function updateSl(uint32 _index, uint64 _newSl) external;

    /**
     * @dev Initiates a new trigger order (for tp/sl/liq/limit/stop orders)
     * @param _packed the packed data of the trigger order (orderType, trader, index)
     */
    function triggerOrder(uint256 _packed) external;

    /**
     * @dev Triggers an order using signed prices (for tp/sl/liq/limit/stop orders)
     * @param _packed the packed data of the trigger order (orderType, trader, index)
     * @param _signedPairPrices the signed lookback pair prices to be used for the trigger order
     */
    function triggerOrderWithSignatures(
        uint256 _packed,
        IPriceAggregator.SignedPairPrices[] calldata _signedPairPrices
    ) external;

    /**
     * @dev Safety function in case oracles don't answer in time, allows caller to cancel a pending order and if relevant claim back any stuck collateral
     * @dev Only allowed for MARKET_OPEN, MARKET_CLOSE, UPDATE_LEVERAGE, MARKET_PARTIAL_OPEN, and MARKET_PARTIAL_CLOSE orders
     * @param _orderIndex the id of the pending order to cancel
     */
    function cancelOrderAfterTimeout(uint32 _orderIndex) external;

    /**
     * @dev Update trade leverage
     * @param _index index of trade
     * @param _newLeverage new leverage (1e3)
     */
    function updateLeverage(uint32 _index, uint24 _newLeverage) external;

    /**
     * @dev Wraps native tokens and updates trade leverage
     * @param _index index of trade
     * @param _newLeverage new leverage (1e3)
     */
    function updateLeverageNative(uint32 _index, uint24 _newLeverage) external payable;

    /**
     * @dev Increase trade position size
     * @param _index index of trade
     * @param _collateralDelta collateral to add (collateral precision)
     * @param _leverageDelta partial trade leverage (1e3)
     * @param _expectedPrice expected price of execution (1e10 precision)
     * @param _maxSlippageP max slippage % (1e3)
     */
    function increasePositionSize(
        uint32 _index,
        uint120 _collateralDelta,
        uint24 _leverageDelta,
        uint64 _expectedPrice,
        uint16 _maxSlippageP
    ) external;

    /**
     * @dev Wraps native token and increase trade position size
     * @param _index index of trade
     * @param _collateralDelta collateral to add (collateral precision)
     * @param _leverageDelta partial trade leverage (1e3)
     * @param _expectedPrice expected price of execution (1e10 precision)
     * @param _maxSlippageP max slippage % (1e3)
     */
    function increasePositionSizeNative(
        uint32 _index,
        uint120 _collateralDelta,
        uint24 _leverageDelta,
        uint64 _expectedPrice,
        uint16 _maxSlippageP
    ) external payable;

    /**
     * @dev Decrease trade position size
     * @param _index index of trade
     * @param _collateralDelta collateral to remove (collateral precision)
     * @param _leverageDelta leverage to reduce by (1e3)
     * @param _expectedPrice expected closing price, used to check max slippage (1e10 precision)
     */
    function decreasePositionSize(
        uint32 _index,
        uint120 _collateralDelta,
        uint24 _leverageDelta,
        uint64 _expectedPrice
    ) external;

    /**
     * @dev Initiates pnl withdrawal request for a trade
     * @param _index index of the trade
     * @param _amountCollateral amount of pnl to claim in collateral tokens (collateral precision)
     */
    function withdrawPositivePnl(uint32 _index, uint120 _amountCollateral) external;

    /**
     * @dev Returns the wrapped native token or address(0) if the current chain, or the wrapped token, is not supported.
     */
    function getWrappedNativeToken() external view returns (address);

    /**
     * @dev Returns true if the token is the wrapped native token for the current chain, where supported.
     * @param _token token address
     */
    function isWrappedNativeToken(address _token) external view returns (bool);

    /**
     * @dev Returns the address a trader delegates his trading actions to
     * @param _trader address of the trader
     */
    function getTradingDelegate(address _trader) external view returns (address);

    /**
     * @dev Returns the current marketOrdersTimeoutBlocks value
     */
    function getMarketOrdersTimeoutBlocks() external view returns (uint16);

    /**
     * @dev Returns whether a user bypasses trigger link costs
     * @param _user address of the user
     */
    function getByPassTriggerLink(address _user) external view returns (bool);

    /**
     * @dev Emitted when marketOrdersTimeoutBlocks is updated
     * @param newValueBlocks the new value of marketOrdersTimeoutBlocks
     */
    event MarketOrdersTimeoutBlocksUpdated(uint256 newValueBlocks);

    /**
     * @dev Emitted when a user is allowed/disallowed to bypass the link cost of triggerOrder
     * @param user address of the user
     * @param bypass whether the user can bypass the link cost of triggerOrder
     */
    event ByPassTriggerLinkUpdated(address indexed user, bool bypass);

    /**
     * @dev Emitted when a manual negative pnl realization is initiated
     * @param orderId order id
     * @param trader trader address
     * @param index index of trade
     * @param isHoldingFeesRealization whether holding fees or negative pnl realization
     */
    event ManualNegativePnlRealizationInitiated(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint32 indexed index,
        bool isHoldingFeesRealization
    );

    /**
     * @dev Emitted when a market order is initiated
     * @param orderId price aggregator order id of the pending market order
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param open whether the market order is for opening or closing a trade
     */
    event MarketOrderInitiated(ITradingStorage.Id orderId, address indexed trader, uint16 indexed pairIndex, bool open);

    /**
     * @dev Emitted when a new limit/stop order is placed
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param index index of the open limit order for caller
     */
    event OpenOrderPlaced(address indexed trader, uint16 indexed pairIndex, uint32 indexed index);

    /**
     *
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param index index of the open limit/stop order for caller
     * @param newPrice new trigger price (1e10 precision)
     * @param newTp new tp (1e10 precision)
     * @param newSl new sl (1e10 precision)
     * @param maxSlippageP new max slippage % (1e3 precision)
     */
    event OpenLimitUpdated(
        address indexed trader,
        uint16 indexed pairIndex,
        uint32 indexed index,
        uint64 newPrice,
        uint64 newTp,
        uint64 newSl,
        uint64 maxSlippageP
    );

    /**
     * @dev Emitted when a limit/stop order is canceled (collateral sent back to trader)
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param index index of the open limit/stop order for caller
     */
    event OpenLimitCanceled(address indexed trader, uint16 indexed pairIndex, uint32 indexed index);

    /**
     * @dev Emitted when a trader initiates a pnl withdrawal request
     * @param orderId order id
     * @param trader address of the trader
     * @param index index of the trade
     * @param amountCollateral amount of positive pnl to claim in collateral tokens (collateral precision)
     */
    event PositivePnlWithdrawalInitiated(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint32 indexed index,
        uint256 amountCollateral
    );

    /**
     * @dev Emitted when a trigger order is initiated (tp/sl/liq/limit/stop orders)
     * @param orderId price aggregator order id of the pending trigger order
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param byPassesLinkCost whether the caller bypasses the link cost
     */
    event TriggerOrderInitiated(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint16 indexed pairIndex,
        bool byPassesLinkCost
    );

    /**
     * @dev Emitted when a pending market order is canceled due to timeout
     * @param pendingOrderId id of the pending order
     * @param pairIndex index of the trading pair
     */
    event ChainlinkCallbackTimeout(ITradingStorage.Id pendingOrderId, uint256 indexed pairIndex);

    /**
     * @dev Emitted when a pending market order is canceled due to timeout and new closeTradeMarket() call failed
     * @param trader address of the trader
     * @param pairIndex index of the trading pair
     * @param index index of the open trade for caller
     */
    event CouldNotCloseTrade(address indexed trader, uint16 indexed pairIndex, uint32 indexed index);

    /**
     * @dev Emitted when a native token is wrapped
     * @param trader address of the trader
     * @param nativeTokenAmount amount of native token wrapped
     */
    event NativeTokenWrapped(address indexed trader, uint256 nativeTokenAmount);

    /**
     * @dev Emitted when a trade's collateral is returned after timeout
     * @param pendingOrderId corresponding order id
     * @param collateralIndex index of collateral
     * @param trader trader address
     * @param collateralAmount collateral amount returned (collateral precision)
     */
    event CollateralReturnedAfterTimeout(
        ITradingStorage.Id pendingOrderId,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 collateralAmount
    );

    error NotWrappedNativeToken();
    error DelegateNotApproved();
    error PriceZero();
    error CollateralNotActive();
    error PriceImpactTooHigh();
    error NoTrade();
    error NoOrder();
    error AlreadyBeingMarketClosed();
    error ConflictingPendingOrder(ITradingStorage.PendingOrderType);
    error WrongLeverage();
    error WrongTp();
    error WrongSl();
    error WaitTimeout();
    error PendingTrigger();
    error NoSl();
    error NoTp();
    error NotYourOrder();
    error DelegatedActionNotAllowed();
    error InsufficientCollateral();
    error WrongFromBlock();
}

File 30 of 51 : ITradingStorageUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITradingStorage.sol";

/**
 * @dev Interface for GNSTradingStorage facet (inherits types and also contains functions, events, and custom errors)
 */
interface ITradingStorageUtils is ITradingStorage {
    /**
     * @dev Initializes the trading storage facet
     * @param _gns address of the gns token
     * @param _gnsStaking address of the gns staking contract
     * @param _collaterals collateral addresses to add
     * @param _gTokens corresponding gToken vault addresses
     */
    function initializeTradingStorage(
        address _gns,
        address _gnsStaking,
        address[] memory _collaterals,
        address[] memory _gTokens
    ) external;

    /**
     * @dev Updates the trading activated state
     * @param _activated the new trading activated state
     */
    function updateTradingActivated(TradingActivated _activated) external;

    /**
     * @dev Lists a new supported collateral (disabled by default).
     * @dev Important: updateCollateralGnsLiquidityPool, updateCollateralUsdPriceFeed, and toggleCollateralActiveState must be called after this function.
     * @param _collateral the address of the collateral
     * @param _gToken the gToken contract of the collateral
     */
    function addCollateral(address _collateral, address _gToken) external;

    /**
     * @dev Toggles the active state of a supported collateral
     * @param _collateralIndex index of the collateral
     */
    function toggleCollateralActiveState(uint8 _collateralIndex) external;

    /**
     * @dev Updates the contracts of a supported collateral trading stack
     * @param _collateral address of the collateral
     * @param _gToken the gToken contract of the collateral
     */
    function updateGToken(address _collateral, address _gToken) external;

    /**
     * @dev Stores a new trade (trade/limit/stop)
     * @param _trade trade to be stored
     * @param _tradeInfo trade info to be stored
     * @param _currentPairPrice the current pair price (1e10)
     */
    function storeTrade(
        Trade memory _trade,
        TradeInfo memory _tradeInfo,
        uint64 _currentPairPrice
    ) external returns (Trade memory);

    /**
     * @dev Updates an existing trade max closing slippage %
     * @param _tradeId id of the trade
     * @param _maxSlippageP new max slippage % (1e3 precision)
     */
    function updateTradeMaxClosingSlippageP(ITradingStorage.Id memory _tradeId, uint16 _maxSlippageP) external;

    /**
     * @dev Updates an open trade collateral
     * @param _tradeId id of updated trade
     * @param _collateralAmount new collateral amount value (collateral precision)
     * @param _leverage new leverage value
     * @param _openPrice new open price value
     * @param _pendingOrderType corresponding pending order type (ignore dust OI delta for leverage updates, refresh trade liq params for partial adds)
     * @param _positionSizeTokenDelta position size token delta (1e18)
     * @param _isPnlPositive whether the pnl is positive (only relevant when closing)
     * @param _currentPairPrice the current pair price (1e10)
     */
    function updateTradePosition(
        Id memory _tradeId,
        uint120 _collateralAmount,
        uint24 _leverage,
        uint64 _openPrice,
        ITradingStorage.PendingOrderType _pendingOrderType,
        uint256 _positionSizeTokenDelta,
        bool _isPnlPositive,
        uint64 _currentPairPrice
    ) external;

    /**
     * @dev Updates an open order details (limit/stop)
     * @param _tradeId id of updated trade
     * @param _openPrice new open price (1e10)
     * @param _tp new take profit price (1e10)
     * @param _sl new stop loss price (1e10)
     * @param _maxSlippageP new max slippage % value (1e3)
     */
    function updateOpenOrderDetails(
        Id memory _tradeId,
        uint64 _openPrice,
        uint64 _tp,
        uint64 _sl,
        uint16 _maxSlippageP
    ) external;

    /**
     * @dev Updates the take profit of an open trade
     * @param _tradeId the trade id
     * @param _newTp the new take profit (1e10 precision)
     */
    function updateTradeTp(Id memory _tradeId, uint64 _newTp) external;

    /**
     * @dev Updates the stop loss of an open trade
     * @param _tradeId the trade id
     * @param _newSl the new sl (1e10 precision)
     */
    function updateTradeSl(Id memory _tradeId, uint64 _newSl) external;

    /**
     * @dev Marks an open trade/limit/stop as closed
     * @param _tradeId the trade id
     * @param _isPnlPositive whether the pnl is positive
     * @param _currentPairPrice the current pair price (1e10)
     */
    function closeTrade(Id memory _tradeId, bool _isPnlPositive, uint64 _currentPairPrice) external;

    /**
     * @dev Stores a new pending order
     * @param _pendingOrder the pending order to be stored
     */
    function storePendingOrder(PendingOrder memory _pendingOrder) external returns (PendingOrder memory);

    /**
     * @dev Closes a pending order
     * @param _orderId the id of the pending order to be closed
     */
    function closePendingOrder(Id memory _orderId) external;

    /**
     * @dev Validates an open trade order (for all order types apart from MARKET_OPEN)
     * @param _trade the trade to validate
     * @param _orderType the pending order type to validate
     */
    function validateOpenTradeOrder(Trade memory _trade, PendingOrderType _orderType) external view;

    /**
     * @dev Returns collateral data by index
     * @param _index the index of the supported collateral
     */
    function getCollateral(uint8 _index) external view returns (Collateral memory);

    /**
     * @dev Returns whether can open new trades with a collateral
     * @param _index the index of the collateral to check
     */
    function isCollateralActive(uint8 _index) external view returns (bool);

    /**
     * @dev Returns whether a collateral has been listed
     * @param _index the index of the collateral to check
     */
    function isCollateralListed(uint8 _index) external view returns (bool);

    /**
     * @dev Returns whether a collateral is the GNS token
     * @param _index the index of the collateral to check
     */
    function isCollateralGns(uint8 _index) external view returns (bool);

    /**
     * @dev Returns the number of supported collaterals
     */
    function getCollateralsCount() external view returns (uint8);

    /**
     * @dev Returns the supported collaterals
     */
    function getCollaterals() external view returns (Collateral[] memory);

    /**
     * @dev Returns the index of a supported collateral
     * @param _collateral the address of the collateral
     */
    function getCollateralIndex(address _collateral) external view returns (uint8);

    /**
     * @dev Returns the collateral index of the GNS token. If 0, GNS is not a collateral.
     */
    function getGnsCollateralIndex() external view returns (uint8);

    /**
     * @dev Returns the trading activated state
     */
    function getTradingActivated() external view returns (TradingActivated);

    /**
     * @dev Returns whether a trader is stored in the traders array
     * @param _trader trader to check
     */
    function getTraderStored(address _trader) external view returns (bool);

    /**
     * @dev Returns the length of the traders array
     */
    function getTradersCount() external view returns (uint256);

    /**
     * @dev Returns all traders that have open trades using a pagination system
     * @param _offset start index in the traders array
     * @param _limit end index in the traders array
     */
    function getTraders(uint32 _offset, uint32 _limit) external view returns (address[] memory);

    /**
     * @dev Returns open trade/limit/stop order
     * @param _trader address of the trader
     * @param _index index of the trade for trader
     */
    function getTrade(address _trader, uint32 _index) external view returns (Trade memory);

    /**
     * @dev Returns all open trades/limit/stop orders for a trader
     * @param _trader address of the trader
     */
    function getTrades(address _trader) external view returns (Trade[] memory);

    /**
     * @dev Returns all trade/limit/stop orders using a pagination system
     * @param _traders list of traders to return trades for
     * @param _offset index of first trade to return
     * @param _limit index of last trade to return
     */
    function getAllTradesForTraders(
        address[] memory _traders,
        uint256 _offset,
        uint256 _limit
    ) external view returns (Trade[] memory);

    /**
     * @dev Returns all trade/limit/stop orders using a pagination system.
     * @dev Calls `getAllTradesForTraders` internally with all traders.
     * @param _offset index of first trade to return
     * @param _limit index of last trade to return
     */
    function getAllTrades(uint256 _offset, uint256 _limit) external view returns (Trade[] memory);

    /**
     * @dev Returns trade info of an open trade/limit/stop order
     * @param _trader address of the trader
     * @param _index index of the trade for trader
     */
    function getTradeInfo(address _trader, uint32 _index) external view returns (TradeInfo memory);

    /**
     * @dev Returns all trade infos of open trade/limit/stop orders for a trader
     * @param _trader address of the trader
     */
    function getTradeInfos(address _trader) external view returns (TradeInfo[] memory);

    /**
     * @dev Returns all trade infos of open trade/limit/stop orders using a pagination system
     * @param _traders list of traders to return tradeInfo for
     * @param _offset index of first tradeInfo to return
     * @param _limit index of last tradeInfo to return
     */
    function getAllTradeInfosForTraders(
        address[] memory _traders,
        uint256 _offset,
        uint256 _limit
    ) external view returns (TradeInfo[] memory);

    /**
     * @dev Returns all trade infos of open trade/limit/stop orders using a pagination system.
     * @dev Calls `getAllTradeInfosForTraders` internally with all traders.
     * @param _offset index of first tradeInfo to return
     * @param _limit index of last tradeInfo to return
     */
    function getAllTradeInfos(uint256 _offset, uint256 _limit) external view returns (TradeInfo[] memory);

    /**
     * @dev Returns a pending ordeer
     * @param _orderId id of the pending order
     */
    function getPendingOrder(Id memory _orderId) external view returns (PendingOrder memory);

    /**
     * @dev Returns all pending orders for a trader
     * @param _user address of the trader
     */
    function getPendingOrders(address _user) external view returns (PendingOrder[] memory);

    /**
     * @dev Returns all pending orders using a pagination system
     * @param _traders list of traders to return pendingOrder for
     * @param _offset index of first pendingOrder to return
     * @param _limit index of last pendingOrder to return
     */
    function getAllPendingOrdersForTraders(
        address[] memory _traders,
        uint256 _offset,
        uint256 _limit
    ) external view returns (PendingOrder[] memory);

    /**
     * @dev Returns all pending orders using a pagination system
     * @dev Calls `getAllPendingOrdersForTraders` internally with all traders.
     * @param _offset index of first pendingOrder to return
     * @param _limit index of last pendingOrder to return
     */
    function getAllPendingOrders(uint256 _offset, uint256 _limit) external view returns (PendingOrder[] memory);

    /**
     * @dev Returns the block number of the pending order for a trade (0 = doesn't exist)
     * @param _tradeId id of the trade
     * @param _orderType pending order type to check
     */
    function getTradePendingOrderBlock(Id memory _tradeId, PendingOrderType _orderType) external view returns (uint256);

    /**
     * @dev Returns the counters of a trader (currentIndex / open count for trades/tradeInfos and pendingOrders mappings)
     * @param _trader address of the trader
     * @param _type the counter type (trade/pending order)
     */
    function getCounters(address _trader, CounterType _type) external view returns (Counter memory);

    /**
     * @dev Returns the counters for a list of traders
     * @param _traders the list of traders
     * @param _type the counter type (trade/pending order)
     */
    function getCountersForTraders(
        address[] calldata _traders,
        CounterType _type
    ) external view returns (Counter[] memory);

    /**
     * @dev Returns the address of the gToken for a collateral stack
     * @param _collateralIndex the index of the supported collateral
     */
    function getGToken(uint8 _collateralIndex) external view returns (address);

    /**
     * @dev Returns the liquidation params for a trade
     * @param _trader address of the trader
     * @param _index index of the trade for trader
     */
    function getTradeLiquidationParams(
        address _trader,
        uint32 _index
    ) external view returns (IPairsStorage.GroupLiquidationParams memory);

    /**
     * @dev Returns all trade liquidation params of open trade/limit/stop orders for a trader
     * @param _trader address of the trader
     */
    function getTradesLiquidationParams(
        address _trader
    ) external view returns (IPairsStorage.GroupLiquidationParams[] memory);

    /**
     * @dev Returns all trade liquidation params of open trade/limit/stop orders using a pagination system
     * @param _traders list of traders to return liq params for
     * @param _offset index of first liq param to return
     * @param _limit index of last liq param to return
     */
    function getAllTradesLiquidationParamsForTraders(
        address[] memory _traders,
        uint256 _offset,
        uint256 _limit
    ) external view returns (IPairsStorage.GroupLiquidationParams[] memory);

    /**
     * @dev Returns all trade liquidation params of open trade/limit/stop orders using a pagination system
     * @dev Calls `getAllTradesLiquidationParamsForTraders` internally with all traders.
     * @param _offset index of first liq param to return
     * @param _limit index of last liq param to return
     */
    function getAllTradesLiquidationParams(
        uint256 _offset,
        uint256 _limit
    ) external view returns (IPairsStorage.GroupLiquidationParams[] memory);

    /**
     * @dev Returns the current contracts version
     */
    function getCurrentContractsVersion() external view returns (ITradingStorage.ContractsVersion);

    /**
     * @dev Returns the contracts version for a trade
     * @param _trader address of the trader
     * @param _index index of the trade
     */
    function getTradeContractsVersion(
        address _trader,
        uint32 _index
    ) external view returns (ITradingStorage.ContractsVersion);

    /**
     * @dev Returns the corresponding lookback fromBlock for a trigger
     * @param _trader address of the trader
     * @param _index index of the trade
     * @param _orderType trigger order type
     */
    function getLookbackFromBlock(
        address _trader,
        uint32 _index,
        ITradingStorage.PendingOrderType _orderType
    ) external view returns (uint32);

    /**
     * @dev Emitted when the trading activated state is updated
     * @param activated the new trading activated state
     */
    event TradingActivatedUpdated(TradingActivated activated);

    /**
     * @dev Emitted when a new supported collateral is added
     * @param collateral the address of the collateral
     * @param index the index of the supported collateral
     * @param gToken the gToken contract of the collateral
     */
    event CollateralAdded(address collateral, uint8 index, address gToken);

    /**
     * @dev Emitted when an existing supported collateral active state is updated
     * @param index the index of the supported collateral
     * @param isActive the new active state
     */
    event CollateralUpdated(uint8 indexed index, bool isActive);

    /**
     * @dev Emitted when an existing supported collateral is disabled (can still close trades but not open new ones)
     * @param index the index of the supported collateral
     */
    event CollateralDisabled(uint8 index);

    /**
     * @dev Emitted when the contracts of a supported collateral trading stack are updated
     * @param collateral the address of the collateral
     * @param index the index of the supported collateral
     * @param gToken the gToken contract of the collateral
     */
    event GTokenUpdated(address collateral, uint8 index, address gToken);

    /**
     * @dev Emitted when a new trade is stored
     * @param user trade user
     * @param index trade index
     * @param trade the trade stored
     * @param tradeInfo the trade info stored
     * @param liquidationParams the trade liquidation params stored
     */
    event TradeStored(
        address indexed user,
        uint32 indexed index,
        Trade trade,
        TradeInfo tradeInfo,
        IPairsStorage.GroupLiquidationParams liquidationParams
    );

    /**
     * @dev Emitted when the max closing slippage % of an open trade is updated
     * @param user trade user
     * @param index trade index
     * @param maxClosingSlippageP new max closing slippage % value (1e3 precision)
     */
    event TradeMaxClosingSlippagePUpdated(address indexed user, uint32 indexed index, uint16 maxClosingSlippageP);

    /**
     * @dev Emitted when an open trade collateral is updated
     * @param user trade user
     * @param index trade index
     * @param collateralAmount new collateral value (collateral precision)
     */
    event TradeCollateralUpdated(address indexed user, uint32 indexed index, uint120 collateralAmount);

    /**
     * @dev Emitted when an open trade collateral is updated
     * @param user trade user
     * @param index trade index
     * @param collateralAmount new collateral value (collateral precision)
     * @param leverage new leverage value (1e3)
     * @param openPrice new open price value (1e10)
     * @param newSl new sl price (1e10)
     * @param newPositionSizeToken new position size in token amount (1e18)
     * @param pendingOrderType corresponding pending order type
     * @param isPnlPositive true if trade pnl is positive (only relevant when closing)
     */
    event TradePositionUpdated(
        address indexed user,
        uint32 indexed index,
        uint120 collateralAmount,
        uint24 leverage,
        uint64 openPrice,
        uint64 newSl,
        uint160 newPositionSizeToken,
        ITradingStorage.PendingOrderType pendingOrderType,
        bool isPnlPositive
    );

    /**
     * @dev Emitted when an existing trade/limit order/stop order is updated
     * @param user trade user
     * @param index trade index
     * @param openPrice new open price value (1e10)
     * @param tp new take profit value (1e10)
     * @param sl new stop loss value (1e10)
     * @param maxSlippageP new max slippage % value (1e3)
     */
    event OpenOrderDetailsUpdated(
        address indexed user,
        uint32 indexed index,
        uint64 openPrice,
        uint64 tp,
        uint64 sl,
        uint16 maxSlippageP
    );

    /**
     * @dev Emitted when the take profit of an open trade is updated
     * @param user trade user
     * @param index trade index
     * @param newTp the new take profit (1e10 precision)
     */
    event TradeTpUpdated(address indexed user, uint32 indexed index, uint64 newTp);

    /**
     * @dev Emitted when the stop loss of an open trade is updated
     * @param user trade user
     * @param index trade index
     * @param newSl the new sl (1e10 precision)
     */
    event TradeSlUpdated(address indexed user, uint32 indexed index, uint64 newSl);

    /**
     * @dev Emitted when an open trade is closed
     * @param user trade user
     * @param index trade index
     * @param isPnlPositive true if trade pnl is positive
     */
    event TradeClosed(address indexed user, uint32 indexed index, bool isPnlPositive);

    /**
     * @dev Emitted when a new pending order is stored
     * @param pendingOrder the pending order stored
     */
    event PendingOrderStored(PendingOrder pendingOrder);

    /**
     * @dev Emitted when a pending order is closed
     * @param orderId the id of the pending order closed
     */
    event PendingOrderClosed(Id orderId);

    error MissingCollaterals();
    error CollateralAlreadyActive();
    error CollateralAlreadyDisabled();
    error TradePositionSizeZero();
    error TradeOpenPriceZero();
    error TradePairNotListed();
    error TradeTpInvalid();
    error TradeSlInvalid();
    error MaxSlippageZero();
    error TradeInfoCollateralPriceUsdZero();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITriggerRewards.sol";

/**
 * @dev Interface for GNSTriggerRewards facet (inherits types and also contains functions, events, and custom errors)
 */
interface ITriggerRewardsUtils is ITriggerRewards {
    /**
     *
     * @dev Initializes parameters for trigger rewards facet
     * @param _timeoutBlocks blocks after which a trigger times out
     */
    function initializeTriggerRewards(uint16 _timeoutBlocks) external;

    /**
     *
     * @dev Updates the blocks after which a trigger times out
     * @param _timeoutBlocks blocks after which a trigger times out
     */
    function updateTriggerTimeoutBlocks(uint16 _timeoutBlocks) external;

    /**
     *
     * @dev Distributes GNS rewards to oracles for a specific trigger
     * @param _rewardGns total GNS reward to be distributed among oracles
     */
    function distributeTriggerReward(uint256 _rewardGns) external;

    /**
     * @dev Claims pending GNS trigger rewards for the caller
     * @param _oracle address of the oracle
     */
    function claimPendingTriggerRewards(address _oracle) external;

    /**
     *
     * @dev Returns current triggerTimeoutBlocks value
     */
    function getTriggerTimeoutBlocks() external view returns (uint16);

    /**
     *
     * @dev Checks if an order is active (exists and has not timed out)
     * @param _orderBlock block number of the order
     */
    function hasActiveOrder(uint256 _orderBlock) external view returns (bool);

    /**
     *
     * @dev Returns the pending GNS trigger rewards for an oracle
     * @param _oracle address of the oracle
     */
    function getTriggerPendingRewardsGns(address _oracle) external view returns (uint256);

    /**
     *
     * @dev Emitted when timeoutBlocks is updated
     * @param timeoutBlocks blocks after which a trigger times out
     */
    event TriggerTimeoutBlocksUpdated(uint16 timeoutBlocks);

    /**
     *
     * @dev Emitted when trigger rewards are distributed for a specific order
     * @param rewardsPerOracleGns reward in GNS distributed per oracle
     * @param oraclesCount number of oracles rewarded
     */
    event TriggerRewarded(uint256 rewardsPerOracleGns, uint256 oraclesCount);

    /**
     *
     * @dev Emitted when pending GNS trigger rewards are claimed by an oracle
     * @param oracle address of the oracle
     * @param rewardsGns GNS rewards claimed
     */
    event TriggerRewardsClaimed(address oracle, uint256 rewardsGns);

    error TimeoutBlocksZero();
    error NoPendingTriggerRewards();
}

File 32 of 51 : IUpdateLeverageUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IUpdateLeverage.sol";
import "../types/ITradingStorage.sol";
import "../types/ITradingCallbacks.sol";

/**
 * @dev Interface for leverage updates
 */
interface IUpdateLeverageUtils is IUpdateLeverage {
    /**
     * @param orderId request order id
     * @param trader address of trader
     * @param pairIndex index of pair
     * @param index index of trade
     * @param isIncrease true if increase leverage, false if decrease
     * @param newLeverage new leverage value (1e3)
     */
    event LeverageUpdateInitiated(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint256 indexed pairIndex,
        uint256 indexed index,
        bool isIncrease,
        uint256 newLeverage
    );

    /**
     * @param orderId request order id
     * @param isIncrease true if leverage increased, false if decreased
     * @param cancelReason cancel reason (executed if none)
     * @param collateralIndex collateral index
     * @param trader address of trader
     * @param pairIndex index of pair
     * @param index index of trade
     * @param oraclePrice current oracle price (1e10)
     * @param collateralDelta collateral delta (collateral precision)
     * @param values useful values (new collateral, new leverage, liq price, gov fee collateral)
     */
    event LeverageUpdateExecuted(
        ITradingStorage.Id orderId,
        bool isIncrease,
        ITradingCallbacks.CancelReason cancelReason,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 pairIndex,
        uint256 indexed index,
        uint256 oraclePrice,
        uint256 collateralDelta,
        IUpdateLeverage.UpdateLeverageValues values
    );
}

File 33 of 51 : IUpdatePositionSizeUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/IUpdatePositionSize.sol";
import "../types/ITradingStorage.sol";
import "../types/ITradingCallbacks.sol";

/**
 * @dev Interface for position size updates
 */
interface IUpdatePositionSizeUtils is IUpdatePositionSize {
    /**
     * @param orderId request order id
     * @param trader address of the trader
     * @param pairIndex index of the pair
     * @param index index of user trades
     * @param isIncrease true if increase position size, false if decrease
     * @param collateralDelta collateral delta (collateral precision)
     * @param leverageDelta leverage delta (1e3)
     */
    event PositionSizeUpdateInitiated(
        ITradingStorage.Id orderId,
        address indexed trader,
        uint256 indexed pairIndex,
        uint256 indexed index,
        bool isIncrease,
        uint256 collateralDelta,
        uint256 leverageDelta
    );

    /**
     * @param orderId request order id
     * @param cancelReason cancel reason if canceled or none if executed
     * @param collateralIndex collateral index
     * @param trader address of trader
     * @param pairIndex index of pair
     * @param index index of trade
     * @param long true for long, false for short
     * @param oraclePrice oracle price (1e10)
     * @param collateralPriceUsd collateral price in USD (1e8)
     * @param collateralDelta collateral delta (collateral precision)
     * @param leverageDelta leverage delta (1e3)
     * @param values important values (new open price, new leverage, new collateral, etc.)
     */
    event PositionSizeIncreaseExecuted(
        ITradingStorage.Id orderId,
        ITradingCallbacks.CancelReason cancelReason,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 pairIndex,
        uint256 indexed index,
        bool long,
        uint256 oraclePrice,
        uint256 collateralPriceUsd,
        uint256 collateralDelta,
        uint256 leverageDelta,
        IUpdatePositionSize.IncreasePositionSizeValues values
    );

    /**
     * @param orderId request order id
     * @param cancelReason cancel reason if canceled or none if executed
     * @param collateralIndex collateral index
     * @param trader address of trader
     * @param pairIndex index of pair
     * @param index index of trade
     * @param long true for long, false for short
     * @param oraclePrice oracle price (1e10)
     * @param collateralPriceUsd collateral price in USD (1e8)
     * @param collateralDelta collateral delta (collateral precision)
     * @param leverageDelta leverage delta (1e3)
     * @param values important values (pnl, new leverage, new collateral, etc.)
     */
    event PositionSizeDecreaseExecuted(
        ITradingStorage.Id orderId,
        ITradingCallbacks.CancelReason cancelReason,
        uint8 indexed collateralIndex,
        address indexed trader,
        uint256 pairIndex,
        uint256 indexed index,
        bool long,
        uint256 oraclePrice,
        uint256 collateralPriceUsd,
        uint256 collateralDelta,
        uint256 leverageDelta,
        IUpdatePositionSize.DecreasePositionSizeValues values
    );

    error InvalidIncreasePositionSizeInput();
    error InvalidDecreasePositionSizeInput();
    error NewPositionSizeSmaller();
}

File 34 of 51 : IAddressStore.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSAddressStore facet
 */
interface IAddressStore {
    enum Role {
        GOV_TIMELOCK,
        GOV,
        MANAGER,
        GOV_EMERGENCY,
        GOV_EMERGENCY_TIMELOCK
    }

    struct Addresses {
        address gns;
        address gnsStaking;
        address treasury;
    }

    struct AddressStore {
        uint256 __deprecated; // previously globalAddresses (gns token only, 1 slot)
        mapping(address => mapping(Role => bool)) accessControl;
        Addresses globalAddresses;
        uint256[7] __gap1; // gap for global addresses
        // insert new storage here
        uint256[38] __gap2; // gap for rest of diamond storage
    }
}

File 35 of 51 : IBorrowingFees.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./IPairsStorage.sol";

/**
 * @dev Contains the types for the GNSBorrowingFees facet
 */
interface IBorrowingFees {
    struct BorrowingFeesStorage {
        mapping(uint8 => mapping(uint16 => BorrowingData)) pairs;
        mapping(uint8 => mapping(uint16 => BorrowingPairGroup[])) pairGroups;
        mapping(uint8 => mapping(uint16 => OpenInterest)) pairOisBeforeV10;
        mapping(uint8 => mapping(uint16 => BorrowingData)) groups;
        mapping(uint8 => mapping(uint16 => OpenInterest)) groupOis;
        mapping(uint8 => mapping(address => mapping(uint32 => BorrowingInitialAccFees))) initialAccFees;
        mapping(uint8 => mapping(uint16 => BorrowingFeePerBlockCap)) pairFeePerBlockCaps;
        BorrowingFeePerBlockCap feePerBlockCap;
        uint256[42] __gap;
    }

    struct BorrowingData {
        uint32 feePerBlock; // 1e10 (%)
        uint64 accFeeLong; // 1e10 (%)
        uint64 accFeeShort; // 1e10 (%)
        uint48 accLastUpdatedBlock;
        uint48 feeExponent;
    }

    struct BorrowingPairGroup {
        uint16 groupIndex;
        uint48 block;
        uint64 initialAccFeeLong; // 1e10 (%)
        uint64 initialAccFeeShort; // 1e10 (%)
        uint64 prevGroupAccFeeLong; // 1e10 (%)
        uint64 prevGroupAccFeeShort; // 1e10 (%)
        uint64 pairAccFeeLong; // 1e10 (%)
        uint64 pairAccFeeShort; // 1e10 (%)
        uint64 __placeholder; // might be useful later
    }

    struct OpenInterest {
        uint72 long; // 1e10 (collateral)
        uint72 short; // 1e10 (collateral)
        uint72 max; // 1e10 (collateral)
        uint40 __placeholder; // might be useful later
    }

    struct BorrowingInitialAccFees {
        uint64 accPairFee; // 1e10 (%)
        uint64 accGroupFee; // 1e10 (%)
        uint48 block;
        uint80 __placeholder; // might be useful later
    }

    struct BorrowingPairParams {
        uint16 groupIndex;
        uint32 feePerBlock; // 1e10 (%)
        uint48 feeExponent;
        uint72 maxOi;
    }

    struct BorrowingGroupParams {
        uint32 feePerBlock; // 1e10 (%)
        uint72 maxOi; // 1e10
        uint48 feeExponent;
    }

    struct BorrowingFeePerBlockCap {
        uint32 minP; // 1e3 (%)
        uint32 maxP; // 1e3 (%)
    }

    struct BorrowingFeeInput {
        uint8 collateralIndex;
        address trader;
        uint16 pairIndex;
        uint32 index;
        bool long;
        uint256 collateral; // 1e18 | 1e6 (collateral)
        uint256 leverage; // 1e3
        uint256 currentPairPrice; // 1e10
    }

    struct LiqPriceInput {
        uint8 collateralIndex;
        address trader;
        uint16 pairIndex;
        uint32 index;
        uint64 openPrice; // 1e10
        bool long;
        uint256 collateral; // 1e18 | 1e6 (collateral)
        uint256 leverage; // 1e3
        int256 additionalFeeCollateral; // 1e18 | 1e6 (collateral)
        IPairsStorage.GroupLiquidationParams liquidationParams;
        uint64 currentPairPrice; // 1e10
        bool isCounterTrade;
        uint256 partialCloseMultiplier; // 1e18
        bool beforeOpened;
    }

    struct PendingBorrowingAccFeesInput {
        uint64 accFeeLong; // 1e10 (%)
        uint64 accFeeShort; // 1e10 (%)
        uint256 oiLong; // 1e18 | 1e6
        uint256 oiShort; // 1e18 | 1e6
        uint32 feePerBlock; // 1e10
        uint256 currentBlock;
        uint256 accLastUpdatedBlock;
        uint72 maxOi; // 1e10
        uint48 feeExponent;
        uint128 collateralPrecision;
        BorrowingFeePerBlockCap feePerBlockCap;
    }

    // Useful to avoid stack too deep errors
    struct AccFeesDeltaValues {
        bool moreShorts;
        uint256 blockDistance;
        uint256 maxOiScaled; // 1e18 | 1e6
        uint256 netOi; // 1e18 | 1e6
        uint256 minNetOi; // 1e18 | 1e6
        uint256 maxNetOi; // 1e18 | 1e6
        uint256 cappedNetOi; // 1e18 | 1e6
    }

    struct GetTradeBorrowingFeeValues {
        BorrowingInitialAccFees initialFees;
        BorrowingPairGroup firstPairGroup;
        uint256 borrowingFeeP; // 1e10 (%)
    }
}

File 36 of 51 : IChainConfig.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSChainConfig facet
 */
interface IChainConfig {
    struct ChainConfigStorage {
        uint256 reentrancyLock; // HAS TO BE FIRST AND TAKE A FULL SLOT (GNSReentrancyGuard expects it)
        uint16 nativeTransferGasLimit; // 16 bits. 64,535 max value
        bool nativeTransferEnabled; // When true, the diamond is allowed to unwrap native tokens on transfer out
        uint232 __placeholder;
        uint256[48] __gap;
    }
}

File 37 of 51 : IDiamondStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @author Nick Mudge <[email protected]> (https://twitter.com/mudgen)
 * @author Gains Network
 * @dev Based on EIP-2535: Diamonds (https://eips.ethereum.org/EIPS/eip-2535)
 * @dev Follows diamond-3 implementation (https://github.com/mudgen/diamond-3-hardhat/)
 * @dev Contains the types used in the diamond management contracts.
 */
interface IDiamondStorage {
    struct DiamondStorage {
        // maps function selector to the facet address and
        // the position of the selector in the facetFunctionSelectors.selectors array
        mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
        // maps facet addresses to function selectors
        mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
        // facet addresses
        address[] facetAddresses;
        address[47] __gap;
    }

    struct FacetAddressAndPosition {
        address facetAddress;
        uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
    }

    struct FacetFunctionSelectors {
        bytes4[] functionSelectors;
        uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
    }

    enum FacetCutAction {
        ADD,
        REPLACE,
        REMOVE,
        NOP
    }

    struct FacetCut {
        address facetAddress;
        FacetCutAction action;
        bytes4[] functionSelectors;
    }
}

File 38 of 51 : IFeeTiers.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSFeeTiers facet
 */
interface IFeeTiers {
    struct FeeTiersStorage {
        // Volume Fee Tiers
        FeeTier[8] feeTiers;
        mapping(uint256 => uint256) groupVolumeMultipliers; // groupIndex (pairs storage) => multiplier (1e3)
        mapping(address => TraderInfo) traderInfos; // trader => TraderInfo
        mapping(address => mapping(uint32 => TraderDailyInfo)) traderDailyInfos; // trader => day => TraderDailyInfo
        mapping(address => TraderEnrollment) traderEnrollments; // trader => TraderEnrollment
        mapping(address => uint224) unclaimedPoints; // trader => points (1e18)
        // Staking Tiers
        FeeTier[8] gnsStakingTiers;
        mapping(address => GnsStakingInfo) gnsStakingInfos; // trader => staking info
        address gnsVaultAddress; // gGNS or any other GNS ERC4626 vault
        bool useGnsVaultBalance; // if true, gnsVaultAddress balance is used for tier calculation
        uint88 __placeholder;
        // Gap
        uint256[27] __gap;
    }

    enum TraderEnrollmentStatus {
        ENROLLED,
        EXCLUDED
    }

    enum CreditType {
        IMMEDIATE,
        CLAIMABLE
    }

    struct FeeTier {
        uint32 feeMultiplier; // 1e3
        uint32 pointsThreshold; // 0 precision; GNS amount or volume points
    }

    struct TraderInfo {
        uint32 lastDayUpdated;
        uint224 trailingPoints; // 1e18
    }

    struct TraderDailyInfo {
        uint32 feeMultiplierCache; // 1e3
        uint224 points; // 1e18
    }

    struct TraderEnrollment {
        TraderEnrollmentStatus status;
        uint248 __placeholder;
    }

    struct GnsStakingInfo {
        uint88 stakedGns; // 1e18
        uint88 stakedVaultGns; // 1e18
        uint24 bonusAmount; // 0 precision
        uint32 stakeTimestamp;
        uint32 feeMultiplierCache; // 1e3
    }
}

File 39 of 51 : IFundingFees.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./ITradingStorage.sol";
import "./IPriceImpact.sol";

/**
 * @dev Contains the types for the GNSFundingFees facet
 */
interface IFundingFees {
    struct FundingFeesStorage {
        mapping(uint8 => mapping(uint16 => PairGlobalParams)) pairGlobalParams;
        mapping(uint8 => mapping(uint16 => FundingFeeParams)) pairFundingFeeParams;
        mapping(uint8 => mapping(uint16 => BorrowingFeeParams)) pairBorrowingFeeParams;
        mapping(uint8 => mapping(uint16 => PairFundingFeeData)) pairFundingFeeData;
        mapping(uint8 => mapping(uint16 => PairBorrowingFeeData)) pairBorrowingFeeData;
        mapping(address => mapping(uint32 => TradeFeesData)) tradeFeesData;
        mapping(address => mapping(uint32 => UiRealizedPnlData)) tradeUiRealizedPnlData;
        mapping(uint32 => PendingParamUpdate) pendingParamUpdates;
        uint256[42] __gap;
    }

    enum ParamUpdateType {
        SKEW_COEFFICIENT_PER_YEAR,
        ABSOLUTE_VELOCITY_PER_YEAR_CAP,
        ABSOLUTE_RATE_PER_SECOND_CAP,
        THETA_THRESHOLD_USD,
        FUNDING_FEES_ENABLED,
        APR_MULTIPLIER_ENABLED,
        BORROWING_RATE_PER_SECOND_P,
        BORROWING_PAIR
    }

    struct PairGlobalParams {
        /**
         * @dev Max skew in collateral tokens allowed when opening a trade / partial adding
         * @dev Min: 0 (= disabled)
         * @dev Precision: 1e-10
         * @dev Max: 120,892,581,961,462 (= 120m USD if collateral/usd = 1e-6)
         * @dev If left uninitialized (0), max skew is disabled
         */
        uint80 maxSkewCollateral;
        uint176 __placeholder;
    }

    struct FundingFeeParams {
        /**
         * @dev Yearly velocity coefficient of the funding rate % / second, it is multiplied by the net exposure in tokens.
         * @dev Precision: 1e-26 => 10^20 token exposure (= 100m USD, 1 collateral = 1e-6 USD, current pair price = 1e-6), funding APR += 31.536% each year (+= 0.0864% each day)
         * @dev Max: 5.19e7 => 1e-8 collateral exposure (= 10k USD, 1 collateral = 1e6 USD, current pair price = 1e6), funding APR += 16,374,427% each year (+= 44,861% each day, += 1,869% each hour)
         * @dev If left uninitialized (0), the funding rate velocity will stay at 0
         */
        uint112 skewCoefficientPerYear;
        /**
         * @dev Absolute cap on the yearly velocity of the funding rate % / second (same when funding positive or negative).
         * @dev Precision: 1e-7 => 3.15% APR absolute increase per year (+= 0.00864% each day)
         * @dev Theoretical max: 1.67 => max 52,908,625% APR absolute increase per year (+= 144,955% each day, += 6,039% each hour)
         * @dev If left uninitialized (0), the funding rate velocity will stay at 0
         */
        uint24 absoluteVelocityPerYearCap;
        /**
         * @dev Cap on the absolute value of the funding rate % / second.
         * @dev Precision: 1e-10 => 0.0031536% APR
         * @dev Theoretical max: 0.0016 => 52,908% APR
         * @dev True cap: 0.0003170979 => 10,000% APR
         * @dev If left uninitialized (0), the funding rate will stay at 0
         */
        uint24 absoluteRatePerSecondCap;
        /**
         * @dev Minimum net exposure in USD required for funding rate velocity to be != 0.
         * @dev Precision: 1 USD (no decimals)
         * @dev Max: 4,294,967,295 USD
         * @dev If left uninitialized (0), there will be no minimum exposure threshold
         */
        uint32 thetaThresholdUsd;
        /**
         * @dev When set to true, enables funding fees on the pair (funding rate always resumes from last rate after funding fees were disabled)
         * @dev When set to false, disables funding fees on the pair
         * @dev If left uninitialized (false), funding fees are disabled by default on the pair
         */
        bool fundingFeesEnabled;
        /**
         * @dev When set to true, enables earning side APR multiplier (earning APR = paying APR * paying OI / earning OI)
         * @dev When set to false, disables earning side APR multiplier (paying APR = earning APR)
         * @dev If left uninitialized (false), earning side APR multiplier is disabled by default on the pair
         */
        bool aprMultiplierEnabled;
        uint48 __placeholder;
    }

    struct BorrowingFeeParams {
        /**
         * @dev Borrowing rate % / second for a given pair.
         * @dev Precision: 1e-10 => 0.0031536% APR
         * @dev Theoretical max: 0.0016 => 52,908% APR
         * @dev True cap: 0.0000317097 => 1,000% APR
         * @dev If left uninitialized (0), the borrowing rate is 0
         */
        uint24 borrowingRatePerSecondP;
        uint232 __placeholder;
    }

    struct PairFundingFeeData {
        /**
         * @dev Accumulated funding fees % weighted by pair price (unit: fee collateral per 100 units of OI in pair amount)
         * @dev To know the funding fee in collateral tokens for a trade, do (current acc fee - initial acc fee) * position size collateral / entry price / 1e10 / 100.
         * @dev Step: 1e-20%; min step = lowest funding rate % per second * 1 second * lowest pair price = 1e-20% (no issues with rounding down)
         * @dev Max: 1.7e18; max possible value = max funding % / second * max timestamp * max pair price * 100 (smaller side cap) = 0.0016 * 4,294,967,295 * 1e6 * 100 = 6.87e14
         * @dev Acc funding fees use funding rate % / second precision of 1e-10 => min/step APR = 0.0031536%
         */
        int128 accFundingFeeLongP;
        int128 accFundingFeeShortP;
        /**
         * @dev Funding rate % / second when the net exposure or funding fee parameters last changed.
         * @dev The true current rate is different depending on the current funding rate velocity and the timestamp of the last update.
         * @dev Precision: 1e-18% => 3.15e-11% APR; min step = lowest velocity per year * 1 second / 1 year = 1e-10 * 1 / (86400*365) = 3.17e-18 (no issues with rounding down)
         * @dev Theoretical max: 0.036 => 1,136,204% APR
         * @dev True cap: 0.0003171 => 10,000% APR
         */
        int56 lastFundingRatePerSecondP;
        /**
         * @dev Timestamp of last accumulated funding fees update
         * @dev Max: 4,294,967,295 (Feb 07 2106)
         */
        uint32 lastFundingUpdateTs;
        uint168 __placeholder;
    }

    struct PairBorrowingFeeData {
        /**
         * @dev Accumulated borrowing fees % weighted by pair price (unit: fee collateral per 100 units of OI in pair amount)
         * @dev To know the borrowing fee in collateral tokens for a trade, do (current acc fee - initial acc fee) * position size collateral / entry price / 1e10 / 100.
         * @dev Precision: 1e-20%; min step = lowest borrowing rate % per second * 1 second * lowest pair price = 1e-20% (no issues with rounding down)
         * @dev Max: 3.4e18; max possible value = max borrowing % / second * max timestamp * max pair price = 0.0016 * 4,294,967,295 * 1e6 = 6.87e12
         */
        uint128 accBorrowingFeeP;
        /**
         * @dev Timestamp of last accumulated borrowing fees update
         * @dev Max: 4,294,967,295 (Feb 07 2106)
         */
        uint32 lastBorrowingUpdateTs;
        uint96 __placeholder;
    }

    struct TradeFeesData {
        /**
         * @dev Realized trading fees impact trade value and collateral in diamond (already sent) and realized pnl only impacts trade value.
         * @dev Trading fees/Holding fees/Realized negative/positive pnl don't impact trade collateral/position size, they are stored separately here.
         * @dev They bring the liquidation price closer or further away depending on the sign.
         * @dev Precision: collateral precision
         */
        uint128 realizedTradingFeesCollateral;
        int128 realizedPnlCollateral;
        /**
         * @dev The following variables reduce the collateral available in diamond without impacting the trade value.
         * @dev It's cleaner than to increase realized trading fees and compensate by realizing positive pnl.
         * @dev Precision: collateral precision
         */
        uint128 manuallyRealizedNegativePnlCollateral;
        uint128 alreadyTransferredNegativePnlCollateral;
        /**
         * @dev The following variable increases the collateral available in diamond without impacting the trade value.
         * @dev Virtual available collateral in diamond (collateral precision) is important for leverage increases (= collateral withdrawals)
         * @dev It allows maintaining the same trade value and having no impact on other vars used to calculate available in diamond
         * @dev While never allowing a trade's available collateral in diamond to go below zero.
         * @dev If the user deposits collateral, available in diamond should always increase instead of going from negative to zero.
         * @dev Precision: collateral precision
         */
        uint128 virtualAvailableCollateralInDiamond;
        uint128 __placeholder;
        /**
         * @dev Used to know how much pending funding/borrowing fees a trade has to pay.
         * @dev When trade position size changes, updated to new acc funding/borrowing fees, and pending existing holding fees are stored separately.
         * @dev Precision: same as PairFundingFeeData.accFundingFeeLongP/accFundingFeeShortP and PairBorrowingFeeData.accBorrowingFeeP
         */
        int128 initialAccFundingFeeP;
        uint128 initialAccBorrowingFeeP;
    }

    struct UiRealizedPnlData {
        /**
         * @dev Trading action fees charged on the open trade (open, partial add, partial close, etc.)
         * @dev Precision: collateral precision
         */
        uint128 realizedTradingFeesCollateral;
        /**
         * @dev Old borrowing fees realized on the open trade
         * @dev Precision: collateral precision
         */
        uint128 realizedOldBorrowingFeesCollateral;
        /**
         * @dev New borrowing fees realized on the open trade
         * @dev Precision: collateral precision
         */
        uint128 realizedNewBorrowingFeesCollateral;
        /**
         * @dev Funding fees realized on the open trade
         * @dev Precision: collateral precision
         */
        int128 realizedFundingFeesCollateral;
        /**
         * @dev Realized pnl of all previous partial closes on the open trade
         * @dev Precision: collateral precision
         */
        int128 realizedPnlPartialCloseCollateral;
        /**
         * @dev All pnl withdrawn on the open trade
         * @dev Precision: collateral precision
         */
        uint128 pnlWithdrawnCollateral;
    }

    struct PendingParamUpdate {
        uint8 collateralIndex;
        uint16 pairIndex;
        ParamUpdateType updateType;
        uint224 newValue; /// @custom:dev uint224 is bigger than any of the funding/borrowing fee params, so no overflow possible
    }

    struct FundingFeeValues {
        IPriceImpact.PairOiToken pairOiToken; // 1e18
        int256 netExposureToken; // 1e18
        int256 netExposureUsd; // 1e10
        uint256 secondsSinceLastUpdate;
        int40 currentVelocityPerYear; // 1e10
        int256 avgFundingRatePerSecondP; // 1e18 (%)
        int256 currentPairPriceInt; // 1e10
        uint256 secondsToReachZeroRate;
        int256 fundingFeesDeltaP; // 1e20 (%)
        uint256 longAprMultiplier; // 1e20
        uint256 shortAprMultiplier; // 1e20
    }

    struct FundingParamCallbackInput {
        uint8 collateralIndex;
        uint16 pairIndex;
        uint224 newValue; // precision depends on parameter
    }

    struct TradeHoldingFees {
        int256 fundingFeeCollateral; // collateral precision
        uint256 borrowingFeeCollateral; // collateral precision
        uint256 borrowingFeeCollateral_old; // collateral precision
        int256 totalFeeCollateral; // collateral precision
    }

    struct RealizeTradingFeesValues {
        ITradingStorage.Trade trade;
        uint256 liqPrice; // 1e10
        uint128 newRealizedFeesCollateral; // collateral precision
        int128 newRealizedPnlCollateral; // collateral precision
        uint256 amountSentFromVaultCollateral; // collateral precision
    }
}

File 40 of 51 : IOtc.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSPairsStorage facet
 */
interface IOtc {
    struct OtcStorage {
        mapping(uint8 => uint256) collateralBalances; // collateralIndex => available OTC value (collateral precision)
        OtcConfig otcConfig;
        uint256[47] __gap;
    }

    struct OtcConfig {
        address gnsTreasury; /// @custom:deprecated Use `AddressStore.globalAddresses.treasury` instead
        uint64 treasuryShareP; // %, 1e10 precision
        uint64 stakingShareP; // %, 1e10 precision
        uint64 burnShareP; // %, 1e10 precision
        uint64 premiumP; // %, 1e10 precision
    }
}

File 41 of 51 : IPairsStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSPairsStorage facet
 */
interface IPairsStorage {
    struct PairsStorage {
        mapping(uint256 => Pair) pairs;
        mapping(uint256 => Group) groups;
        mapping(uint256 => Fee) fees; /// @custom:deprecated
        mapping(string => mapping(string => bool)) isPairListed;
        mapping(uint256 => uint256) pairCustomMaxLeverage; // 1e3 precision
        uint256 currentOrderId; /// @custom:deprecated
        uint256 pairsCount;
        uint256 groupsCount;
        uint256 feesCount;
        mapping(uint256 => GroupLiquidationParams) groupLiquidationParams;
        mapping(uint256 => FeeGroup) feeGroups;
        GlobalTradeFeeParams globalTradeFeeParams;
        mapping(uint16 => CounterTradeSettings) pairCounterTradeSettings;
        uint256[37] __gap;
    }

    struct Pair {
        string from;
        string to;
        Feed feed; /// @custom:deprecated
        uint256 spreadP; // 1e10
        uint256 groupIndex;
        uint256 feeIndex;
    }

    struct Group {
        string name;
        bytes32 job; /// @custom:deprecated
        uint256 minLeverage; // 1e3 precision
        uint256 maxLeverage; // 1e3 precision
    }

    struct GlobalTradeFeeParams {
        uint24 referralFeeP; // 1e3 (%)
        uint24 govFeeP; // 1e3 (%)
        uint24 triggerOrderFeeP; // 1e3 (%)
        uint24 gnsOtcFeeP; // 1e3 (%)
        uint24 gTokenFeeP; // 1e3 (%)
        uint136 __placeholder;
    }

    struct FeeGroup {
        uint40 totalPositionSizeFeeP; // 1e10 (%)
        uint40 totalLiqCollateralFeeP; // 1e10 (%)
        uint40 oraclePositionSizeFeeP; // 1e10 (%)
        uint32 minPositionSizeUsd; // 1e3
        uint104 __placeholder;
    }

    struct TradeFees {
        uint256 totalFeeCollateral; // collateral precision
        uint256 referralFeeCollateral; // collateral precision
        uint256 govFeeCollateral; // collateral precision
        uint256 triggerOrderFeeCollateral; // collateral precision
        uint256 gnsOtcFeeCollateral; // collateral precision
        uint256 gTokenFeeCollateral; // collateral precision
    }

    struct GroupLiquidationParams {
        uint40 maxLiqSpreadP; // 1e10 (%)
        uint40 startLiqThresholdP; // 1e10 (%)
        uint40 endLiqThresholdP; // 1e10 (%)
        uint24 startLeverage; // 1e3
        uint24 endLeverage; // 1e3
    }

    struct CounterTradeSettings {
        uint24 maxLeverage; // 1e3
        uint16 feeRateMultiplier; // 1e3
        uint216 __placeholder;
    }

    // Deprecated structs
    enum FeedCalculation {
        DEFAULT,
        INVERT,
        COMBINE
    } /// @custom:deprecated
    struct Feed {
        address feed1;
        address feed2;
        FeedCalculation feedCalculation;
        uint256 maxDeviationP;
    } /// @custom:deprecated
    struct Fee {
        string name;
        uint256 openFeeP; // 1e10 (% of position size)
        uint256 closeFeeP; // 1e10 (% of position size)
        uint256 oracleFeeP; // 1e10 (% of position size)
        uint256 triggerOrderFeeP; // 1e10 (% of position size)
        uint256 minPositionSizeUsd; // 1e18 (collateral x leverage, useful for min fee)
    } /// @custom:deprecated
}

File 42 of 51 : IPriceAggregator.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";

import "./ITradingStorage.sol";
import "./ITradingCallbacks.sol";
import "../IChainlinkFeed.sol";
import "../ILiquidityPool.sol";

/**
 * @dev Contains the types for the GNSPriceAggregator facet
 */
interface IPriceAggregator {
    struct PriceAggregatorStorage {
        IChainlinkFeed linkUsdPriceFeed;
        uint24 twapInterval; // seconds
        uint8 minAnswers;
        uint24 maxMarketDeviationP; // 1e3 %
        uint24 maxLookbackDeviationP; // 1e3 %
        uint16 __placeholder;
        bytes32[2] jobIds;
        address[] oracles;
        mapping(uint8 => LiquidityPoolInfo) collateralGnsLiquidityPools;
        mapping(uint8 => IChainlinkFeed) collateralUsdPriceFeed;
        mapping(bytes32 => Order) orders;
        mapping(address => mapping(uint32 => uint256[])) orderAnswersLegacy; /// @custom:deprecated
        // Chainlink Client state start
        LinkTokenInterface linkErc677;
        uint8 limitJobCount; // max value 255
        uint88 limitJobIndex; // max value 3e26 runs
        uint256 requestCount;
        mapping(bytes32 => address) pendingRequests;
        // Chainlink Client state end
        bytes32 paramUpdateJobId; /// @custom:deprecated
        mapping(address => mapping(uint32 => OrderAnswer[])) orderAnswers;
        mapping(uint16 => OrderAnswer[]) signedOrderAnswersTemporary;
        mapping(uint16 => ITradingCallbacks.AggregatorAnswer) signedMediansTemporary;
        uint16[] signedPairIndicesTemporary;
        uint256[34] __gap;
    }

    struct LiquidityPoolInfo {
        ILiquidityPool pool;
        bool isGnsToken0InLp;
        PoolType poolType;
        uint80 __placeholder;
    }

    struct Order {
        address user;
        uint32 index;
        ITradingStorage.PendingOrderType orderType;
        uint16 pairIndex;
        bool isLookback;
        uint32 __placeholder;
    }

    struct OrderAnswer {
        /// @custom:dev max price = type(uint56.max) / 1e10 = 7,205,759
        uint56 open;
        uint56 high;
        uint56 low;
        uint56 current;
        uint32 ts;
    }

    struct LiquidityPoolInput {
        ILiquidityPool pool;
        PoolType poolType;
    }

    struct GetPriceInput {
        uint8 collateralIndex;
        uint16 pairIndex;
        ITradingStorage.PendingOrder pendingOrder;
        uint256 positionSizeCollateral; // collateral precision
        uint256 fromBlock;
        bool isCounterTrade;
    }

    struct SignedPairPrices {
        uint8 signerId; // index in oracles array of price aggregator facet
        uint32 expiryTs;
        bool isLookback;
        uint32 fromBlock;
        bytes signature;
        uint16[] pairIndices;
        OrderAnswer[] prices;
    }

    enum PoolType {
        UNISWAP_V3,
        ALGEBRA_v1_9,
        CONSTANT_VALUE
    }
}

File 43 of 51 : IPriceImpact.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSPriceImpact facet
 */
interface IPriceImpact {
    struct PriceImpactStorage {
        OiWindowsSettings oiWindowsSettings;
        mapping(uint48 => mapping(uint256 => mapping(uint256 => PairOi))) windows; // duration => pairIndex => windowId => Oi
        mapping(uint256 => PairDepth) pairDepths; // pairIndex => depth (USD)
        mapping(address => mapping(uint32 => TradePriceImpactInfo)) tradePriceImpactInfos; // deprecated
        mapping(uint256 => PairFactors) pairFactors;
        uint40 negPnlCumulVolMultiplier;
        uint216 __placeholder;
        mapping(address => bool) protectionCloseFactorWhitelist;
        mapping(address => mapping(uint256 => UserPriceImpact)) userPriceImpact; // address => pair => UserPriceImpact
        mapping(uint8 => mapping(uint16 => uint256)) pairSkewDepths; // collateral index => pairIndex => depth (tokens, 1e18)
        mapping(uint8 => mapping(uint16 => PairOiCollateral)) pairOiAfterV10Collateral; // collateral index => pairIndex => open interest (collateral precision)
        mapping(uint8 => mapping(uint16 => PairOiToken)) pairOiAfterV10Token; // collateral index => pairIndex => open interest (1e18)
        mapping(uint256 => PairDepthBands) pairDepthBands; // pairIndex => depth bands
        DepthBandsMapping depthBandsMapping; // global mapping from band indices to band percentage offsets
        uint256[36] __gap;
    }

    struct OiWindowsSettings {
        uint48 startTs;
        uint48 windowsDuration;
        uint48 windowsCount;
    }

    struct PairOi {
        uint128 oiLongUsd; // 1e18 USD
        uint128 oiShortUsd; // 1e18 USD
    }

    struct PairOiCollateral {
        uint128 oiLongCollateral; // collateral precision
        uint128 oiShortCollateral; // collateral precision
    }

    struct PairOiToken {
        uint128 oiLongToken; // 1e18
        uint128 oiShortToken; // 1e18
    }

    struct OiWindowUpdate {
        address trader;
        uint32 index;
        uint48 windowsDuration;
        uint256 pairIndex;
        uint256 windowId;
        bool long;
        bool open;
        bool isPnlPositive;
        uint128 openInterestUsd; // 1e18 USD
    }

    struct PairDepth {
        uint128 onePercentDepthAboveUsd; // USD
        uint128 onePercentDepthBelowUsd; // USD
    }

    struct PairFactors {
        uint40 protectionCloseFactor; // 1e10; max 109.95x
        uint32 protectionCloseFactorBlocks;
        uint40 cumulativeFactor; // 1e10; max 109.95x
        bool exemptOnOpen;
        bool exemptAfterProtectionCloseFactor;
        uint128 __placeholder;
    }

    struct UserPriceImpact {
        uint16 cumulVolPriceImpactMultiplier; // 1e3
        uint16 fixedSpreadP; // 1e3 %
        uint224 __placeholder;
    }

    struct PriceImpactValues {
        PairFactors pairFactors;
        bool protectionCloseFactorWhitelist;
        UserPriceImpact userPriceImpact;
        bool protectionCloseFactorActive;
        uint256 depth; // USD
        bool tradePositiveSkew;
        int256 tradeSkewMultiplier;
        int256 priceImpactDivider;
    }

    /**
     * @dev Each slot encodes cumulative liquidity percentages for specific bands.
     * Percentages are in basis points (eg. 10,000 = 100% => percentages with 2 decimals).
     * Max value: 65535/1e2 = 655.35%
     */
    struct PairDepthBands {
        uint256 aboveSlot1; // totalDepthUsd (uint32, no decimals) + 14 x uint16 band cumulative liquidity percentages
        uint256 aboveSlot2; // 16 x uint16 band cumulative liquidity percentages
        uint256 belowSlot1; // totalDepthUsd (uint32, no decimals) + 14 x uint16 band cumulative liquidity percentages
        uint256 belowSlot2; // 16 x uint16 band cumulative liquidity percentages
    }

    /**
     * @dev Each slot encodes cumulative offset percentages from mid price for specific bands.
     * Same encoding as PairDepthBands, but totalDepthUsd is zeroed.
     * Percentages are in parts per million (eg. 1,000,000 = 100% => percentages with 4 decimals).
     * Max value: 65535/1e4 = 6.5535%
     */
    struct DepthBandsMapping {
        uint256 slot1; // first 32 bits empty, 14 x uint16 band offset percentages
        uint256 slot2; // 16 x uint16 band offset percentages
    }

    // Working struct for convenience
    struct DepthBandParameters {
        uint256 pairSlot1;
        uint256 pairSlot2;
        uint256 mappingSlot1;
        uint256 mappingSlot2;
    }

    // Deprecated
    struct TradePriceImpactInfo {
        uint128 lastWindowOiUsd;
        uint128 __placeholder;
    }
}

File 44 of 51 : IReferrals.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSReferrals facet
 */
interface IReferrals {
    struct ReferralsStorage {
        mapping(address => AllyDetails) allyDetails;
        mapping(address => ReferrerDetails) referrerDetails;
        mapping(address => address) referrerByTrader;
        uint256 allyFeeP; // % (of referrer fees going to allies, eg. 10)
        uint256 startReferrerFeeP; // % (of referrer fee when 0 volume referred, eg. 75)
        uint256 openFeeP; /// @custom:deprecated
        uint256 targetVolumeUsd; // USD (to reach maximum referral system fee, eg. 1e8)
        mapping(address => ReferralSettingsOverrides) referralSettingsOverrides;
        uint256[42] __gap;
    }

    struct AllyDetails {
        address[] referrersReferred;
        uint256 volumeReferredUsd; // 1e18
        uint256 pendingRewardsGns; // 1e18
        uint256 totalRewardsGns; // 1e18
        uint256 totalRewardsValueUsd; // 1e18
        bool active;
    }

    struct ReferrerDetails {
        address ally;
        address[] tradersReferred;
        uint256 volumeReferredUsd; // 1e18
        uint256 pendingRewardsGns; // 1e18
        uint256 totalRewardsGns; // 1e18
        uint256 totalRewardsValueUsd; // 1e18
        bool active;
    }

    struct ReferralSettingsOverrides {
        uint24 referralFeeOverrideP; // % of total trading fee (1e3), 0 means it uses globalTradeFeeParams value
        uint24 allyFeeOverrideP; // % of total trading fee (1e3), 0 means it uses default allyFeeP value
        uint208 __placeholder;
    }
}

File 45 of 51 : ITradingCallbacks.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../types/ITradingStorage.sol";
import "../libraries/ITradingCommonUtils.sol";

/**
 * @dev Contains the types for the GNSTradingCallbacks facet
 */
interface ITradingCallbacks {
    struct TradingCallbacksStorage {
        uint8 vaultClosingFeeP;
        uint248 __placeholder;
        mapping(uint8 => uint256) pendingGovFees; // collateralIndex => pending gov fee (collateral)
        uint256[48] __gap;
    }

    enum CancelReason {
        NONE,
        PAUSED, // deprecated
        MARKET_CLOSED, // deprecated
        SLIPPAGE,
        TP_REACHED,
        SL_REACHED,
        EXPOSURE_LIMITS,
        PRICE_IMPACT,
        MAX_LEVERAGE,
        NO_TRADE,
        WRONG_TRADE,
        NOT_HIT,
        LIQ_REACHED,
        COUNTER_TRADE_CANCELED
    }

    struct AggregatorAnswer {
        ITradingStorage.Id orderId;
        uint64 open;
        uint64 high;
        uint64 low;
        uint64 current;
    }

    // Useful to avoid stack too deep errors
    struct Values {
        int256 profitP;
        uint256 executionPrice;
        uint256 executionPriceRaw;
        uint256 liqPrice;
        uint256 amountSentToTrader;
        uint256 collateralPriceUsd;
        bool exactExecution;
        uint32 limitIndex;
        ITradingCommonUtils.TradePriceImpact priceImpact;
        CancelReason cancelReason;
        uint256 collateralToReturn;
        uint120 newCollateralAmount;
        uint256 newEffectiveLeverage;
        uint256 pnlWithdrawnCollateral;
        uint256 openingFeeCollateral;
    }

    struct PnlWithdrawalValues {
        ITradingStorage.Trade trade;
        uint64 currentPairPrice;
        uint256 positionSizeCollateral;
        ITradingCommonUtils.TradePriceImpact priceImpact;
        int256 pnlPercent;
        int256 withdrawablePositivePnlCollateral;
        uint256 pnlInputCollateral;
        uint256 pnlWithdrawnCollateral;
        uint256 withdrawablePositivePnlCollateralUint;
        uint256 finalGovFeeCollateral;
    }
}

File 46 of 51 : ITradingInteractions.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSTradingInteractions facet
 */
interface ITradingInteractions {
    struct TradingInteractionsStorage {
        address senderOverride; // 160 bits
        uint16 marketOrdersTimeoutBlocks; // 16 bits
        uint80 __placeholder;
        mapping(address => address) delegations;
        mapping(address => bool) byPassTriggerLink;
        uint256[47] __gap;
    }
}

File 47 of 51 : ITradingStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./IPairsStorage.sol";

/**
 * @dev Contains the types for the GNSTradingStorage facet
 */
interface ITradingStorage {
    struct TradingStorage {
        TradingActivated tradingActivated; // 8 bits
        uint8 lastCollateralIndex; // 8 bits
        uint8 gnsCollateralIndex; // 8 bits
        uint232 __placeholder; // 232 bits
        mapping(uint8 => Collateral) collaterals;
        mapping(uint8 => address) gTokens;
        mapping(address => uint8) collateralIndex;
        mapping(address => mapping(uint32 => Trade)) trades;
        mapping(address => mapping(uint32 => TradeInfo)) tradeInfos;
        mapping(address => mapping(uint32 => mapping(PendingOrderType => uint256))) tradePendingOrderBlock;
        mapping(address => mapping(uint32 => PendingOrder)) pendingOrders;
        mapping(address => mapping(CounterType => Counter)) userCounters;
        address[] traders;
        mapping(address => bool) traderStored;
        mapping(address => mapping(uint32 => IPairsStorage.GroupLiquidationParams)) tradeLiquidationParams;
        uint256[38] __gap;
    }

    enum PendingOrderType {
        MARKET_OPEN,
        MARKET_CLOSE,
        LIMIT_OPEN,
        STOP_OPEN,
        TP_CLOSE,
        SL_CLOSE,
        LIQ_CLOSE,
        UPDATE_LEVERAGE,
        MARKET_PARTIAL_OPEN,
        MARKET_PARTIAL_CLOSE,
        PARAM_UPDATE, // deprecated
        PNL_WITHDRAWAL,
        MANUAL_HOLDING_FEES_REALIZATION,
        MANUAL_NEGATIVE_PNL_REALIZATION
    }

    enum CounterType {
        TRADE,
        PENDING_ORDER
    }

    enum TradeType {
        TRADE,
        LIMIT,
        STOP
    }

    enum TradingActivated {
        ACTIVATED,
        CLOSE_ONLY,
        PAUSED
    }

    enum ContractsVersion {
        BEFORE_V9_2,
        V9_2,
        V10
    }

    struct Collateral {
        // slot 1
        address collateral; // 160 bits
        bool isActive; // 8 bits
        uint88 __placeholder; // 88 bits
        // slot 2
        uint128 precision;
        uint128 precisionDelta;
    }

    struct Id {
        address user; // 160 bits
        uint32 index; // max: 4,294,967,295
    }

    struct Trade {
        // slot 1
        address user; // 160 bits
        uint32 index; // max: 4,294,967,295
        uint16 pairIndex; // max: 65,535
        uint24 leverage; // 1e3; max: 16,777.215
        bool long; // 8 bits
        bool isOpen; // 8 bits
        uint8 collateralIndex; // max: 255
        // slot 2
        TradeType tradeType; // 8 bits
        uint120 collateralAmount; // collateral precision; max: 3.402e+38
        uint64 openPrice; // 1e10; max: 1.8e19
        uint64 tp; // 1e10; max: 1.8e19
        // slot 3
        uint64 sl; // 1e10; max: 1.8e19
        bool isCounterTrade;
        /// @dev Warning this position size  in token amount is calculated using position size collateral / entry price, without taking into account skew price impact
        /// At the moment it is only used to calculate skew price impact, once we refactor formulas to use it for pnl for example we'll need to re-calculate it based on real entry price
        /// And once we refactor to USD position sizes we'll have to convert it from collateral to USD
        uint160 positionSizeToken; // 1e18, assuming 1e-9 collateral price, 1e-9 pair price => max value is 1.46 trillion USD (1e12)
        uint24 __placeholder;
    }

    struct TradeInfo {
        uint32 createdBlock; // for lookbacks
        uint32 tpLastUpdatedBlock; // for lookbacks
        uint32 slLastUpdatedBlock; // for lookbacks
        uint16 maxSlippageP; // 1e3 (%)
        uint48 lastOiUpdateTs; // deprecated
        uint48 collateralPriceUsd; // 1e8 collateral price at trade open
        ContractsVersion contractsVersion;
        uint32 lastPosIncreaseBlock; // for protection close factor
        uint8 __placeholder;
    }

    struct PendingOrder {
        // slots 1-3
        Trade trade;
        // slot 4
        address user; // 160 bits
        uint32 index; // max: 4,294,967,295
        bool isOpen; // 8 bits
        PendingOrderType orderType; // 8 bits
        uint32 createdBlock; // max: 4,294,967,295
        uint16 maxSlippageP; // 1e3 (%), max: 65.535%
    }

    struct Counter {
        uint32 currentIndex;
        uint32 openCount;
        uint192 __placeholder;
    }

    struct UpdateTradePositionValues {
        uint32 blockNumber;
        uint64 newSl;
        uint160 newPositionSizeToken;
    }
}

File 48 of 51 : ITriggerRewards.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 * @dev Contains the types for the GNSTriggerRewards facet
 */
interface ITriggerRewards {
    struct TriggerRewardsStorage {
        uint16 triggerTimeoutBlocks; // 16 bits
        uint240 __placeholder; // 240 bits
        mapping(address => uint256) pendingRewardsGns;
        uint256[48] __gap;
    }
}

File 49 of 51 : ITypes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./IDiamondStorage.sol";
import "./IPairsStorage.sol";
import "./IReferrals.sol";
import "./IFeeTiers.sol";
import "./IPriceImpact.sol";
import "./ITradingStorage.sol";
import "./ITriggerRewards.sol";
import "./ITradingInteractions.sol";
import "./ITradingCallbacks.sol";
import "./IBorrowingFees.sol";
import "./IPriceAggregator.sol";
import "./IOtc.sol";
import "./IChainConfig.sol";
import "./IFundingFees.sol";

/**
 * @dev Contains the types of all diamond facets
 */
interface ITypes is
    IDiamondStorage,
    IPairsStorage,
    IReferrals,
    IFeeTiers,
    IPriceImpact,
    ITradingStorage,
    ITriggerRewards,
    ITradingInteractions,
    ITradingCallbacks,
    IBorrowingFees,
    IPriceAggregator,
    IOtc,
    IChainConfig,
    IFundingFees
{

}

File 50 of 51 : IUpdateLeverage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/**
 *
 * @dev Interface for leverage updates types
 */
interface IUpdateLeverage {
    /// @dev Update leverage input values
    struct UpdateLeverageInput {
        address user;
        uint32 index;
        uint24 newLeverage; // 1e3
    }

    /// @dev Useful values for increase leverage callback
    struct UpdateLeverageValues {
        uint256 newLeverage; // 1e3
        uint256 newCollateralAmount; // collateral precision
        uint256 existingLiqPrice; // 1e10
        uint256 newLiqPrice; // 1e10
        uint256 govFeeCollateral; // collateral precision
        uint256 newEffectiveLeverage; // 1e3
        uint256 totalTradeAvailableCollateralInDiamond; // collateral precision
        uint256 availableCollateralInDiamond; // collateral precision
    }
}

File 51 of 51 : IUpdatePositionSize.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "../libraries/ITradingCommonUtils.sol";

/**
 *
 * @dev Interface for position size updates types
 */
interface IUpdatePositionSize {
    /// @dev Request decrease position input values
    struct DecreasePositionSizeInput {
        address user;
        uint32 index;
        uint120 collateralDelta; // collateral precision
        uint24 leverageDelta; // 1e3
        uint64 expectedPrice; // 1e10
    }

    /// @dev Request increase position input values
    struct IncreasePositionSizeInput {
        address user;
        uint32 index;
        uint120 collateralDelta; // collateral precision
        uint24 leverageDelta; // 1e3
        uint64 expectedPrice; // 1e10
        uint16 maxSlippageP; // 1e3 (%)
    }

    /// @dev Useful values for decrease position size callback
    struct DecreasePositionSizeValues {
        bool isLeverageUpdate;
        uint256 positionSizeCollateralDelta; // collateral precision
        uint256 existingPositionSizeCollateral; // collateral precision
        uint256 existingLiqPrice; // 1e10
        uint256 newLiqPrice; // 1e10
        ITradingCommonUtils.TradePriceImpact priceImpact;
        int256 existingPnlPercent; // 1e10 (%)
        int256 partialRawPnlCollateral; // collateral precision
        int256 partialNetPnlCollateral; // collateral precision
        int256 pnlToRealizeCollateral; // collateral precision
        uint256 closingFeeCollateral; // collateral precision
        uint256 totalAvailableCollateralInDiamond; // collateral precision
        int256 availableCollateralInDiamond; // collateral precision
        int256 collateralSentToTrader; // collateral precision
        uint120 newCollateralAmount; // collateral precision
        uint24 newLeverage; // 1e3
    }

    /// @dev Useful values for increase position size callback
    struct IncreasePositionSizeValues {
        uint256 positionSizeCollateralDelta; // collateral precision
        uint256 existingPositionSizeCollateral; // collateral precision
        uint256 newPositionSizeCollateral; // collateral precision
        uint256 newCollateralAmount; // collateral precision
        uint256 newLeverage; // 1e3
        ITradingCommonUtils.TradePriceImpact priceImpact;
        int256 existingPnlCollateral; // collateral precision
        uint256 oldPosSizePlusPnlCollateral; // collateral precision
        uint256 newOpenPrice; // 1e10
        uint256 openingFeesCollateral; // collateral precision
        uint256 existingLiqPrice; // 1e10
        uint256 newLiqPrice; // 1e10
        bool isCounterTradeValidated;
        uint256 exceedingPositionSizeCollateral; // collateral precision
        uint256 counterTradeCollateralToReturn; // collateral precision
        uint256 newEffectiveLeverage; // 1e3
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"getAllUserInfo","outputs":[{"components":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"},{"internalType":"uint256[]","name":"allowances","type":"uint256[]"},{"internalType":"bool","name":"protectionCloseFactorWhitelist","type":"bool"},{"components":[{"internalType":"uint16","name":"cumulVolPriceImpactMultiplier","type":"uint16"},{"internalType":"uint16","name":"fixedSpreadP","type":"uint16"},{"internalType":"uint224","name":"__placeholder","type":"uint224"}],"internalType":"struct IPriceImpact.UserPriceImpact[]","name":"userPriceImpacts","type":"tuple[]"},{"components":[{"components":[{"internalType":"uint32","name":"lastDayUpdated","type":"uint32"},{"internalType":"uint224","name":"trailingPoints","type":"uint224"}],"internalType":"struct IFeeTiers.TraderInfo","name":"traderInfo","type":"tuple"},{"components":[{"internalType":"uint88","name":"stakedGns","type":"uint88"},{"internalType":"uint88","name":"stakedVaultGns","type":"uint88"},{"internalType":"uint24","name":"bonusAmount","type":"uint24"},{"internalType":"uint32","name":"stakeTimestamp","type":"uint32"},{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"}],"internalType":"struct IFeeTiers.GnsStakingInfo","name":"gnsStakingInfo","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoLastUpdated","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoCurrent","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoExpired","type":"tuple"},{"components":[{"internalType":"enum IFeeTiers.TraderEnrollmentStatus","name":"status","type":"uint8"},{"internalType":"uint248","name":"__placeholder","type":"uint248"}],"internalType":"struct IFeeTiers.TraderEnrollment","name":"traderEnrollment","type":"tuple"},{"internalType":"uint224","name":"unclaimedPoints","type":"uint224"}],"internalType":"struct GNSReader.FeeTierOutput","name":"feeTierOutput","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"uint16","name":"pairIndex","type":"uint16"},{"internalType":"uint24","name":"leverage","type":"uint24"},{"internalType":"bool","name":"long","type":"bool"},{"internalType":"bool","name":"isOpen","type":"bool"},{"internalType":"uint8","name":"collateralIndex","type":"uint8"},{"internalType":"enum ITradingStorage.TradeType","name":"tradeType","type":"uint8"},{"internalType":"uint120","name":"collateralAmount","type":"uint120"},{"internalType":"uint64","name":"openPrice","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"},{"internalType":"uint64","name":"sl","type":"uint64"},{"internalType":"bool","name":"isCounterTrade","type":"bool"},{"internalType":"uint160","name":"positionSizeToken","type":"uint160"},{"internalType":"uint24","name":"__placeholder","type":"uint24"}],"internalType":"struct ITradingStorage.Trade","name":"trade","type":"tuple"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"bool","name":"isOpen","type":"bool"},{"internalType":"enum ITradingStorage.PendingOrderType","name":"orderType","type":"uint8"},{"internalType":"uint32","name":"createdBlock","type":"uint32"},{"internalType":"uint16","name":"maxSlippageP","type":"uint16"}],"internalType":"struct ITradingStorage.PendingOrder[]","name":"pendingOrders","type":"tuple[]"}],"internalType":"struct GNSReader.UserInfoOutput","name":"userInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"getBalancesAndAllowances","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"},{"internalType":"uint256[]","name":"allowances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint32[]","name":"_days","type":"uint32[]"}],"name":"getExpiredPointsForDays","outputs":[{"internalType":"uint224[]","name":"expiredPoints","type":"uint224[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getPendingOrders","outputs":[{"components":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"uint16","name":"pairIndex","type":"uint16"},{"internalType":"uint24","name":"leverage","type":"uint24"},{"internalType":"bool","name":"long","type":"bool"},{"internalType":"bool","name":"isOpen","type":"bool"},{"internalType":"uint8","name":"collateralIndex","type":"uint8"},{"internalType":"enum ITradingStorage.TradeType","name":"tradeType","type":"uint8"},{"internalType":"uint120","name":"collateralAmount","type":"uint120"},{"internalType":"uint64","name":"openPrice","type":"uint64"},{"internalType":"uint64","name":"tp","type":"uint64"},{"internalType":"uint64","name":"sl","type":"uint64"},{"internalType":"bool","name":"isCounterTrade","type":"bool"},{"internalType":"uint160","name":"positionSizeToken","type":"uint160"},{"internalType":"uint24","name":"__placeholder","type":"uint24"}],"internalType":"struct ITradingStorage.Trade","name":"trade","type":"tuple"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"bool","name":"isOpen","type":"bool"},{"internalType":"enum ITradingStorage.PendingOrderType","name":"orderType","type":"uint8"},{"internalType":"uint32","name":"createdBlock","type":"uint32"},{"internalType":"uint16","name":"maxSlippageP","type":"uint16"}],"internalType":"struct ITradingStorage.PendingOrder[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getProtectionCloseFactorWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUserPriceImpact","outputs":[{"components":[{"internalType":"uint16","name":"cumulVolPriceImpactMultiplier","type":"uint16"},{"internalType":"uint16","name":"fixedSpreadP","type":"uint16"},{"internalType":"uint224","name":"__placeholder","type":"uint224"}],"internalType":"struct IPriceImpact.UserPriceImpact[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGNSMultiCollatDiamond","name":"_diamond","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUserTraderFeeTiers","outputs":[{"components":[{"components":[{"internalType":"uint32","name":"lastDayUpdated","type":"uint32"},{"internalType":"uint224","name":"trailingPoints","type":"uint224"}],"internalType":"struct IFeeTiers.TraderInfo","name":"traderInfo","type":"tuple"},{"components":[{"internalType":"uint88","name":"stakedGns","type":"uint88"},{"internalType":"uint88","name":"stakedVaultGns","type":"uint88"},{"internalType":"uint24","name":"bonusAmount","type":"uint24"},{"internalType":"uint32","name":"stakeTimestamp","type":"uint32"},{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"}],"internalType":"struct IFeeTiers.GnsStakingInfo","name":"gnsStakingInfo","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoLastUpdated","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoCurrent","type":"tuple"},{"components":[{"internalType":"uint32","name":"feeMultiplierCache","type":"uint32"},{"internalType":"uint224","name":"points","type":"uint224"}],"internalType":"struct IFeeTiers.TraderDailyInfo","name":"traderDailyInfoExpired","type":"tuple"},{"components":[{"internalType":"enum IFeeTiers.TraderEnrollmentStatus","name":"status","type":"uint8"},{"internalType":"uint248","name":"__placeholder","type":"uint248"}],"internalType":"struct IFeeTiers.TraderEnrollment","name":"traderEnrollment","type":"tuple"},{"internalType":"uint224","name":"unclaimedPoints","type":"uint224"}],"internalType":"struct GNSReader.FeeTierOutput","name":"output","type":"tuple"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50611ba6806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063bdfda9011161005b578063bdfda901146100eb578063c61f7c5c1461010c578063cb0fd1b91461012c578063d7ee3c371461014c57600080fd5b80634106f38b1461008257806370bbf5e6146100ab57806386ab5413146100cb575b600080fd5b610095610090366004610ec2565b61016f565b6040516100a29190610f27565b60405180910390f35b6100be6100b9366004610f74565b6102af565b6040516100a2919061119a565b6100de6100d9366004610f74565b6105b1565b6040516100a29190611204565b6100fe6100f9366004610ec2565b610723565b6040516100a2929190611248565b61011f61011a366004610ec2565b610913565b6040516100a291906113c9565b61013f61013a366004610f74565b610974565b6040516100a2919061146a565b61015f61015a366004610f74565b610cde565b60405190151581526020016100a2565b60608167ffffffffffffffff81111561018a5761018a611479565b6040519080825280602002602001820160405280156101b3578160200160208202803683370190505b50905060005b828110156102a6576000866001600160a01b031663794d8520878787868181106101e5576101e561148f565b90506020020160208101906101fa91906114b7565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015263ffffffff1660248201526044016040805180830381865afa158015610248573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026c91906115d5565b905080602001518383815181106102855761028561148f565b6001600160e01b0390921660209283029190910190910152506001016101b9565b50949350505050565b60606000836001600160a01b0316630212f0d68460016040518363ffffffff1660e01b81526004016102e29291906115f1565b606060405180830381865afa1580156102ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103239190611617565b90506000816020015163ffffffff1667ffffffffffffffff81111561034a5761034a611479565b60405190808252806020026020018201604052801561042857816020015b604080516102c081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e08301829052610200830182905261022083018290526102408301829052610260830182905261028083018290526102a0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282526000199092019101816103685790505b509050816020015163ffffffff166000036104465791506105ab9050565b60006064836000015163ffffffff161161046157600061046f565b825161046f9060649061169e565b835163ffffffff9182169250600091165b828111156105a3576000886001600160a01b031663c6e729bb60405180604001604052808b6001600160a01b031681526020016001866104c091906116c2565b63ffffffff9081169091526040516001600160e01b031960e085901b16815282516001600160a01b031660048201526020909201511660248201526044016102a060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610540919061189e565b905080606001516105515750610593565b80858461055d81611964565b95508151811061056f5761056f61148f565b6020026020010181905250856020015163ffffffff16831061059157506105a3565b505b61059c8161197d565b9050610480565b509193505050505b92915050565b60606000836001600160a01b031663b81b2b716040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106179190611994565b905060008167ffffffffffffffff81111561063457610634611479565b60405190808252806020026020018201604052801561067f57816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816106525790505b50905060005b828110156102a657604051635a1449ab60e01b81526001600160a01b03868116600483015260248201839052871690635a1449ab90604401606060405180830381865afa1580156106da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fe91906119ad565b8282815181106107105761071061148f565b6020908102919091010152600101610685565b606080828067ffffffffffffffff81111561074057610740611479565b604051908082528060200260200182016040528015610769578160200160208202803683370190505b5092508067ffffffffffffffff81111561078557610785611479565b6040519080825280602002602001820160405280156107ae578160200160208202803683370190505b50915060005b818110156109085760008686838181106107d0576107d061148f565b90506020020160208101906107e591906119ef565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa15801561082f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108539190611994565b8583815181106108655761086561148f565b6020908102919091010152604051636eb1769f60e11b81526001600160a01b0389811660048301528a8116602483015282169063dd62ed3e90604401602060405180830381865afa1580156108be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e29190611994565b8483815181106108f4576108f461148f565b6020908102919091010152506001016107b4565b505094509492505050565b61091b610d67565b61092785858585610723565b602083015281526109388585610cde565b1515604082015261094985856105b1565b60608201526109588585610974565b608082015261096785856102af565b60a0820152949350505050565b61097c610da5565b6000610986610d53565b60405163acbaaf3360e01b81526001600160a01b0385811660048301529192509085169063acbaaf33906024016040805180830381865afa1580156109cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f391906115d5565b82526040516339d51ad160e21b81526001600160a01b03848116600483015285169063e7546b449060240160a060405180830381865afa158015610a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5f9190611a27565b60208301528151516040516303ca6c2960e51b81526001600160a01b03858116600483015263ffffffff90921660248201529085169063794d8520906044016040805180830381865afa158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade91906115d5565b604083810191909152516303ca6c2960e51b81526001600160a01b03848116600483015263ffffffff8316602483015285169063794d8520906044016040805180830381865afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a91906115d5565b60608301526001600160a01b03841663794d852084610b7a601e8561169e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015263ffffffff1660248201526044016040805180830381865afa158015610bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bec91906115d5565b60808301526040516328465fdf60e11b81526001600160a01b03848116600483015285169063508cbfbe906024016040805180830381865afa158015610c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5a9190611ac7565b60a0830152604051634271f5f160e11b81526001600160a01b0384811660048301528516906384e3ebe290602401602060405180830381865afa158015610ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc99190611b18565b6001600160e01b031660c08301525092915050565b6040516315547c4160e11b81526001600160a01b03828116600483015260009190841690632aa8f88290602401602060405180830381865afa158015610d28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4c9190611b33565b9392505050565b6000610d626201518042611b4e565b905090565b6040518060c00160405280606081526020016060815260200160001515815260200160608152602001610d98610da5565b8152602001606081525090565b6040805161012081018252600060e0820181815261010083018290528252825160a081018452818152602080820183905281850183905260608083018490526080808401859052828601939093528551808701875284815280830185905285870152855180870187528481528083018590529085015284518086019095528285528401919091529091908201908152602001610e51604080518082019091526000808252602082015290565b8152600060209091015290565b6001600160a01b0381168114610e7357600080fd5b50565b60008083601f840112610e8857600080fd5b50813567ffffffffffffffff811115610ea057600080fd5b6020830191508360208260051b8501011115610ebb57600080fd5b9250929050565b60008060008060608587031215610ed857600080fd5b8435610ee381610e5e565b93506020850135610ef381610e5e565b9250604085013567ffffffffffffffff811115610f0f57600080fd5b610f1b87828801610e76565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015610f685783516001600160e01b031683529284019291840191600101610f43565b50909695505050505050565b60008060408385031215610f8757600080fd5b8235610f9281610e5e565b91506020830135610fa281610e5e565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b60038110610fd357610fd3610fad565b9052565b600e8110610fd357610fd3610fad565b600081518084526020808501945080840160005b8381101561118f578151805180516001600160a01b031689528085015163ffffffff81168a87015250604081015161103960408b018261ffff169052565b50606081015161105060608b018262ffffff169052565b5060808181015115158a82015260a0808301511515818c015260c08084015160ff16818d015260e08085015190611089908e0182610fc3565b50610100848101516effffffffffffffffffffffffffffff16908d01526101208085015167ffffffffffffffff908116918e0191909152610140808601518216908e015261016080860151909116908d0152610180808501511515908d01526101a0808501516001600160a01b03908116918e01919091526101c09485015162ffffff16948d0194909452878501519093166101e08c0152604084015163ffffffff166102008c0152606084015115156102208c015281840151926111526102408d0185610fd7565b9084015163ffffffff166102608c01529092015161ffff81166102808b0152915061117a9050565b506102a0969096019590820190600101610ffb565b509495945050505050565b602081526000610d4c6020830184610fe7565b60008151808452602080850194506020840160005b8381101561118f578151805161ffff90811689528482015116848901526040908101516001600160e01b031690880152606090960195908201906001016111c2565b602081526000610d4c60208301846111ad565b60008151808452602080850194506020840160005b8381101561118f5781518752958201959082019060010161122c565b60408152600061125b6040830185611217565b828103602084015261126d8185611217565b95945050505050565b60028110610e7357610e73610fad565b805161129181611276565b82526020908101516001600160f81b0316910152565b6112cb828251805163ffffffff1682526020908101516001600160e01b0316910152565b60208101516affffffffffffffffffffff8082511660408501528060208301511660608501525062ffffff6040820151166080840152606081015163ffffffff80821660a08601528060808401511660c0860152505050604081015161134d60e0840182805163ffffffff1682526020908101516001600160e01b0316910152565b506060810151805163ffffffff1661012084015260208101516001600160e01b0316610140840152506080810151805163ffffffff1661016084015260208101516001600160e01b03166101808401525060a08101516113b16101a0840182611286565b5060c001516001600160e01b03166101e09190910152565b60208152600082516102a08060208501526113e86102c0850183611217565b91506020850151601f19808685030160408701526114068483611217565b9350604087015115156060870152606087015191508086850301608087015261142f84836111ad565b93506080870151915061144560a08701836112a7565b60a08701519150808685030183870152506114608382610fe7565b9695505050505050565b61020081016105ab82846112a7565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b63ffffffff81168114610e7357600080fd5b6000602082840312156114c957600080fd5b8135610d4c816114a5565b6040805190810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b60405290565b6040516060810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b6040516101e0810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b8051611579816114a5565b919050565b80516001600160e01b038116811461157957600080fd5b6000604082840312156115a757600080fd5b6115af6114d4565b905081516115bc816114a5565b81526115ca6020830161157e565b602082015292915050565b6000604082840312156115e757600080fd5b610d4c8383611595565b6001600160a01b03831681526040810161160a83611276565b8260208301529392505050565b60006060828403121561162957600080fd5b61163161150b565b825161163c816114a5565b8152602083015161164c816114a5565b6020820152604083015177ffffffffffffffffffffffffffffffffffffffffffffffff8116811461167c57600080fd5b60408201529392505050565b634e487b7160e01b600052601160045260246000fd5b63ffffffff8281168282160390808211156116bb576116bb611688565b5092915050565b818103818111156105ab576105ab611688565b805161157981610e5e565b805161ffff8116811461157957600080fd5b805162ffffff8116811461157957600080fd5b8051801515811461157957600080fd5b805160ff8116811461157957600080fd5b80516003811061157957600080fd5b80516effffffffffffffffffffffffffffff8116811461157957600080fd5b805167ffffffffffffffff8116811461157957600080fd5b60006101e0828403121561177f57600080fd5b61178761153c565b9050611792826116d5565b81526117a06020830161156e565b60208201526117b1604083016116e0565b60408201526117c2606083016116f2565b60608201526117d360808301611705565b60808201526117e460a08301611705565b60a08201526117f560c08301611715565b60c082015261180660e08301611726565b60e0820152610100611819818401611735565b9082015261012061182b838201611754565b9082015261014061183d838201611754565b9082015261016061184f838201611754565b90820152610180611861838201611705565b908201526101a06118738382016116d5565b908201526101c06118858382016116f2565b9082015292915050565b8051600e811061157957600080fd5b60006102a082840312156118b157600080fd5b60405160e0810181811067ffffffffffffffff821117156118e257634e487b7160e01b600052604160045260246000fd5b6040526118ef848461176c565b81526118fe6101e084016116d5565b6020820152611910610200840161156e565b60408201526119226102208401611705565b6060820152611934610240840161188f565b6080820152611946610260840161156e565b60a082015261195861028084016116e0565b60c08201529392505050565b60006001820161197657611976611688565b5060010190565b60008161198c5761198c611688565b506000190190565b6000602082840312156119a657600080fd5b5051919050565b6000606082840312156119bf57600080fd5b6119c761150b565b6119d0836116e0565b81526119de602084016116e0565b602082015261167c6040840161157e565b600060208284031215611a0157600080fd5b8135610d4c81610e5e565b80516affffffffffffffffffffff8116811461157957600080fd5b600060a08284031215611a3957600080fd5b60405160a0810181811067ffffffffffffffff82111715611a6a57634e487b7160e01b600052604160045260246000fd5b604052611a7683611a0c565b8152611a8460208401611a0c565b6020820152611a95604084016116f2565b60408201526060830151611aa8816114a5565b60608201526080830151611abb816114a5565b60808201529392505050565b600060408284031215611ad957600080fd5b611ae16114d4565b825160028110611af057600080fd5b815260208301516001600160f81b0381168114611b0c57600080fd5b60208201529392505050565b600060208284031215611b2a57600080fd5b610d4c8261157e565b600060208284031215611b4557600080fd5b610d4c82611705565b600082611b6b57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212204f4521727aec9df2c27a3ea78bbd89726dcf75cba38d9acb4d513f18d214c16f64736f6c63430008170033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063bdfda9011161005b578063bdfda901146100eb578063c61f7c5c1461010c578063cb0fd1b91461012c578063d7ee3c371461014c57600080fd5b80634106f38b1461008257806370bbf5e6146100ab57806386ab5413146100cb575b600080fd5b610095610090366004610ec2565b61016f565b6040516100a29190610f27565b60405180910390f35b6100be6100b9366004610f74565b6102af565b6040516100a2919061119a565b6100de6100d9366004610f74565b6105b1565b6040516100a29190611204565b6100fe6100f9366004610ec2565b610723565b6040516100a2929190611248565b61011f61011a366004610ec2565b610913565b6040516100a291906113c9565b61013f61013a366004610f74565b610974565b6040516100a2919061146a565b61015f61015a366004610f74565b610cde565b60405190151581526020016100a2565b60608167ffffffffffffffff81111561018a5761018a611479565b6040519080825280602002602001820160405280156101b3578160200160208202803683370190505b50905060005b828110156102a6576000866001600160a01b031663794d8520878787868181106101e5576101e561148f565b90506020020160208101906101fa91906114b7565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015263ffffffff1660248201526044016040805180830381865afa158015610248573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026c91906115d5565b905080602001518383815181106102855761028561148f565b6001600160e01b0390921660209283029190910190910152506001016101b9565b50949350505050565b60606000836001600160a01b0316630212f0d68460016040518363ffffffff1660e01b81526004016102e29291906115f1565b606060405180830381865afa1580156102ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103239190611617565b90506000816020015163ffffffff1667ffffffffffffffff81111561034a5761034a611479565b60405190808252806020026020018201604052801561042857816020015b604080516102c081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e08301829052610200830182905261022083018290526102408301829052610260830182905261028083018290526102a0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282526000199092019101816103685790505b509050816020015163ffffffff166000036104465791506105ab9050565b60006064836000015163ffffffff161161046157600061046f565b825161046f9060649061169e565b835163ffffffff9182169250600091165b828111156105a3576000886001600160a01b031663c6e729bb60405180604001604052808b6001600160a01b031681526020016001866104c091906116c2565b63ffffffff9081169091526040516001600160e01b031960e085901b16815282516001600160a01b031660048201526020909201511660248201526044016102a060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610540919061189e565b905080606001516105515750610593565b80858461055d81611964565b95508151811061056f5761056f61148f565b6020026020010181905250856020015163ffffffff16831061059157506105a3565b505b61059c8161197d565b9050610480565b509193505050505b92915050565b60606000836001600160a01b031663b81b2b716040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106179190611994565b905060008167ffffffffffffffff81111561063457610634611479565b60405190808252806020026020018201604052801561067f57816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816106525790505b50905060005b828110156102a657604051635a1449ab60e01b81526001600160a01b03868116600483015260248201839052871690635a1449ab90604401606060405180830381865afa1580156106da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fe91906119ad565b8282815181106107105761071061148f565b6020908102919091010152600101610685565b606080828067ffffffffffffffff81111561074057610740611479565b604051908082528060200260200182016040528015610769578160200160208202803683370190505b5092508067ffffffffffffffff81111561078557610785611479565b6040519080825280602002602001820160405280156107ae578160200160208202803683370190505b50915060005b818110156109085760008686838181106107d0576107d061148f565b90506020020160208101906107e591906119ef565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa15801561082f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108539190611994565b8583815181106108655761086561148f565b6020908102919091010152604051636eb1769f60e11b81526001600160a01b0389811660048301528a8116602483015282169063dd62ed3e90604401602060405180830381865afa1580156108be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e29190611994565b8483815181106108f4576108f461148f565b6020908102919091010152506001016107b4565b505094509492505050565b61091b610d67565b61092785858585610723565b602083015281526109388585610cde565b1515604082015261094985856105b1565b60608201526109588585610974565b608082015261096785856102af565b60a0820152949350505050565b61097c610da5565b6000610986610d53565b60405163acbaaf3360e01b81526001600160a01b0385811660048301529192509085169063acbaaf33906024016040805180830381865afa1580156109cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f391906115d5565b82526040516339d51ad160e21b81526001600160a01b03848116600483015285169063e7546b449060240160a060405180830381865afa158015610a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5f9190611a27565b60208301528151516040516303ca6c2960e51b81526001600160a01b03858116600483015263ffffffff90921660248201529085169063794d8520906044016040805180830381865afa158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade91906115d5565b604083810191909152516303ca6c2960e51b81526001600160a01b03848116600483015263ffffffff8316602483015285169063794d8520906044016040805180830381865afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a91906115d5565b60608301526001600160a01b03841663794d852084610b7a601e8561169e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015263ffffffff1660248201526044016040805180830381865afa158015610bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bec91906115d5565b60808301526040516328465fdf60e11b81526001600160a01b03848116600483015285169063508cbfbe906024016040805180830381865afa158015610c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5a9190611ac7565b60a0830152604051634271f5f160e11b81526001600160a01b0384811660048301528516906384e3ebe290602401602060405180830381865afa158015610ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc99190611b18565b6001600160e01b031660c08301525092915050565b6040516315547c4160e11b81526001600160a01b03828116600483015260009190841690632aa8f88290602401602060405180830381865afa158015610d28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4c9190611b33565b9392505050565b6000610d626201518042611b4e565b905090565b6040518060c00160405280606081526020016060815260200160001515815260200160608152602001610d98610da5565b8152602001606081525090565b6040805161012081018252600060e0820181815261010083018290528252825160a081018452818152602080820183905281850183905260608083018490526080808401859052828601939093528551808701875284815280830185905285870152855180870187528481528083018590529085015284518086019095528285528401919091529091908201908152602001610e51604080518082019091526000808252602082015290565b8152600060209091015290565b6001600160a01b0381168114610e7357600080fd5b50565b60008083601f840112610e8857600080fd5b50813567ffffffffffffffff811115610ea057600080fd5b6020830191508360208260051b8501011115610ebb57600080fd5b9250929050565b60008060008060608587031215610ed857600080fd5b8435610ee381610e5e565b93506020850135610ef381610e5e565b9250604085013567ffffffffffffffff811115610f0f57600080fd5b610f1b87828801610e76565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015610f685783516001600160e01b031683529284019291840191600101610f43565b50909695505050505050565b60008060408385031215610f8757600080fd5b8235610f9281610e5e565b91506020830135610fa281610e5e565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b60038110610fd357610fd3610fad565b9052565b600e8110610fd357610fd3610fad565b600081518084526020808501945080840160005b8381101561118f578151805180516001600160a01b031689528085015163ffffffff81168a87015250604081015161103960408b018261ffff169052565b50606081015161105060608b018262ffffff169052565b5060808181015115158a82015260a0808301511515818c015260c08084015160ff16818d015260e08085015190611089908e0182610fc3565b50610100848101516effffffffffffffffffffffffffffff16908d01526101208085015167ffffffffffffffff908116918e0191909152610140808601518216908e015261016080860151909116908d0152610180808501511515908d01526101a0808501516001600160a01b03908116918e01919091526101c09485015162ffffff16948d0194909452878501519093166101e08c0152604084015163ffffffff166102008c0152606084015115156102208c015281840151926111526102408d0185610fd7565b9084015163ffffffff166102608c01529092015161ffff81166102808b0152915061117a9050565b506102a0969096019590820190600101610ffb565b509495945050505050565b602081526000610d4c6020830184610fe7565b60008151808452602080850194506020840160005b8381101561118f578151805161ffff90811689528482015116848901526040908101516001600160e01b031690880152606090960195908201906001016111c2565b602081526000610d4c60208301846111ad565b60008151808452602080850194506020840160005b8381101561118f5781518752958201959082019060010161122c565b60408152600061125b6040830185611217565b828103602084015261126d8185611217565b95945050505050565b60028110610e7357610e73610fad565b805161129181611276565b82526020908101516001600160f81b0316910152565b6112cb828251805163ffffffff1682526020908101516001600160e01b0316910152565b60208101516affffffffffffffffffffff8082511660408501528060208301511660608501525062ffffff6040820151166080840152606081015163ffffffff80821660a08601528060808401511660c0860152505050604081015161134d60e0840182805163ffffffff1682526020908101516001600160e01b0316910152565b506060810151805163ffffffff1661012084015260208101516001600160e01b0316610140840152506080810151805163ffffffff1661016084015260208101516001600160e01b03166101808401525060a08101516113b16101a0840182611286565b5060c001516001600160e01b03166101e09190910152565b60208152600082516102a08060208501526113e86102c0850183611217565b91506020850151601f19808685030160408701526114068483611217565b9350604087015115156060870152606087015191508086850301608087015261142f84836111ad565b93506080870151915061144560a08701836112a7565b60a08701519150808685030183870152506114608382610fe7565b9695505050505050565b61020081016105ab82846112a7565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b63ffffffff81168114610e7357600080fd5b6000602082840312156114c957600080fd5b8135610d4c816114a5565b6040805190810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b60405290565b6040516060810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b6040516101e0810167ffffffffffffffff8111828210171561150557634e487b7160e01b600052604160045260246000fd5b8051611579816114a5565b919050565b80516001600160e01b038116811461157957600080fd5b6000604082840312156115a757600080fd5b6115af6114d4565b905081516115bc816114a5565b81526115ca6020830161157e565b602082015292915050565b6000604082840312156115e757600080fd5b610d4c8383611595565b6001600160a01b03831681526040810161160a83611276565b8260208301529392505050565b60006060828403121561162957600080fd5b61163161150b565b825161163c816114a5565b8152602083015161164c816114a5565b6020820152604083015177ffffffffffffffffffffffffffffffffffffffffffffffff8116811461167c57600080fd5b60408201529392505050565b634e487b7160e01b600052601160045260246000fd5b63ffffffff8281168282160390808211156116bb576116bb611688565b5092915050565b818103818111156105ab576105ab611688565b805161157981610e5e565b805161ffff8116811461157957600080fd5b805162ffffff8116811461157957600080fd5b8051801515811461157957600080fd5b805160ff8116811461157957600080fd5b80516003811061157957600080fd5b80516effffffffffffffffffffffffffffff8116811461157957600080fd5b805167ffffffffffffffff8116811461157957600080fd5b60006101e0828403121561177f57600080fd5b61178761153c565b9050611792826116d5565b81526117a06020830161156e565b60208201526117b1604083016116e0565b60408201526117c2606083016116f2565b60608201526117d360808301611705565b60808201526117e460a08301611705565b60a08201526117f560c08301611715565b60c082015261180660e08301611726565b60e0820152610100611819818401611735565b9082015261012061182b838201611754565b9082015261014061183d838201611754565b9082015261016061184f838201611754565b90820152610180611861838201611705565b908201526101a06118738382016116d5565b908201526101c06118858382016116f2565b9082015292915050565b8051600e811061157957600080fd5b60006102a082840312156118b157600080fd5b60405160e0810181811067ffffffffffffffff821117156118e257634e487b7160e01b600052604160045260246000fd5b6040526118ef848461176c565b81526118fe6101e084016116d5565b6020820152611910610200840161156e565b60408201526119226102208401611705565b6060820152611934610240840161188f565b6080820152611946610260840161156e565b60a082015261195861028084016116e0565b60c08201529392505050565b60006001820161197657611976611688565b5060010190565b60008161198c5761198c611688565b506000190190565b6000602082840312156119a657600080fd5b5051919050565b6000606082840312156119bf57600080fd5b6119c761150b565b6119d0836116e0565b81526119de602084016116e0565b602082015261167c6040840161157e565b600060208284031215611a0157600080fd5b8135610d4c81610e5e565b80516affffffffffffffffffffff8116811461157957600080fd5b600060a08284031215611a3957600080fd5b60405160a0810181811067ffffffffffffffff82111715611a6a57634e487b7160e01b600052604160045260246000fd5b604052611a7683611a0c565b8152611a8460208401611a0c565b6020820152611a95604084016116f2565b60408201526060830151611aa8816114a5565b60608201526080830151611abb816114a5565b60808201529392505050565b600060408284031215611ad957600080fd5b611ae16114d4565b825160028110611af057600080fd5b815260208301516001600160f81b0381168114611b0c57600080fd5b60208201529392505050565b600060208284031215611b2a57600080fd5b610d4c8261157e565b600060208284031215611b4557600080fd5b610d4c82611705565b600082611b6b57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212204f4521727aec9df2c27a3ea78bbd89726dcf75cba38d9acb4d513f18d214c16f64736f6c63430008170033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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