GMX
Overview
Decentralized spot and perpetual exchange that allows slippage-free trades on its platform.
Dual-token model
GLP for liquidity providers - receive 70% of platform fees
GMX for governance - receive 30% of platform fees
GMX can be staked for esGMX to earn
Escrowed GMX
Multiplier Points
ETH / AVAX Rewards (from fees)
Traders can swap assets or get perpetual exposure through an asset pool made up of LPs.
Spot trading
swap directly against the liquidity pool
price is determined with Chainlink price feeds and allows zero-slippage trades at that price
fees vary based on the proportion of the assets in the liquidity pool versus the target proportion
Perpetuals trading
traders can open a long or short position on any listed asset with up to 30x leverage
liquidity pool synthetically takes the opposite position of the trader, such that any profit made by the trader is a loss for the liquidity pool and vice versa
Traders pay 0.1% fees on their notional size when opening or closing a position, and a borrow fee for every hour the position is open.
Target weights for assets in the liquidity pool are set according to the positions of the traders. For example, if traders are levered long on ETH, a higher proportion of ETH will be targeted for the liquidity pool.
The execution price on GMX is decided by the Chainlink oracle, so the depth of the liquidity pool does not affect slippage.
Liquidity depth will constrain growth for perpetuals. The protocol reserves an equivalent amount of assets from the liquidity pool as open positions to mitigate the risk of insolvency. As such, the protocol cannot support net open interest beyond the assets available in the liquidity pool.
Depth of the liquidity pool inversely affects the borrowing fee. The borrowing fee is similar to funding rates and is paid every hour. It is calculated as (assets borrowed / total assets in pool * 0.01%). Greater depth ⇒ better pricing for traders.
Contracts
Vault
Vault contract stores deposits and handles the main trading functions.
Deposit: Funds are deposited into the Vault through the minting of GLP tokens
Withdrawal: Funds can be withdrawn from the vault through the burning of GLP tokens
Swap: The vault allows swapping of the tokens held in the vault
Longs: Users can open a long position using the vault. A snapshot of the collateral value is taken when the position is opened. To ensure the vault has sufficient funds to pay out any profits, an amount of ETH equivalent to the position’s size is marked as reserved, for this position, 5 ETH in the vault would be reserved.
Shorts: Users can open a short position using the vault. Stablecoins are required as collateral for shorts and similar to longs, an amount of stablecoins equivalent to the size of the position would be reserved to pay out any profits.
Liquidations: A position can be liquidated by keepers if the losses of the position reduces the collateral to the point where
position size / remaining collateral
is more than the max allowed leverage.
Router
Router contracts provide convenience functions on top of the vault
router handles transferring the tokens to the vault as well as wrapping / unwrapping of native tokens if required
users interact with the router and sends tokens to it, which are then processed and sent to the Vault contract for execution
Position Router
The PositionRouter contract handles a two part transaction process for increasing or decreasing long / short positions.
This process helps to reduce front-running issues:
User sends request to increase / decrease a position to the PositionRouter
A keeper requests the index price from an aggregate of exchanges
The keeper then executes the position at the current index price
If the position cannot be executed within the allowed slippage the request is cancelled and the funds are sent back to the user
Working to integrate with KeeperDAO so that if a price update creates an arbitrage opportunity, profits from the arbitrage are captured and redirected into the pool.
PriceFeeds
The PriceFeed contract accepts submissions from the price feed keeper. This keeper calculates prices using the median price of Binance, Bitfinex and Coinbase. There are two types of keepers:
Price feed keeper: submits prices routinely for swaps
Position keeper: submits prices when executing a position
The vault uses the price from the keeper if it is within a configured percentage of the corresponding Chainlink price. If the price exceeds this threshold then a spread would be created between the bounded price and the Chainlink price.
Prices from the keeper have an expiry of five minutes. if the last price has been submitted more than five minutes ago, the Chainlink price will be used instead.
Liquidations can only occur if the Chainlink price reaches the liquidation price for a position.
Watcher nodes also run to verify that the prices submitted by the keepers have not been tampered with. Watcher nodes continually compute the median price and compare this with the prices submitted by keepers.
Access Control
Parameters that can be adjusted by a controller account currently controlled by the team:
Setting of swap and margin trading fees up to a maximum of 5%
Setting of token weights for the GLP pool, token weights affect the dynamic fees of swaps, these fees are such that a swap which increases the balance towards the specified token weight will be lower, while a swap that moves the token weight away from the desired amounts will have higher fees, the details of the calculation can be found from
Vault.vaultUtils.getSwapFeeBasisPoints
Pausing of swaps or leverage trading for emergency use
Setting of the maximum allowed leverage
Setting of maximum total capacity for long and short positions
Parameters that can be adjusted by a Timelock controlled by the team:
Listing of new tokens
Updating
Vault.priceFeed
Updating
Vault.vaultUtils
, the VaultUtils contract validates the opening and closing of positions and also specifies how fees are calculatedUpdating of
gov
values
The Timelock works by requiring a 24 hour gap between when the full details of an action is signalled on-chain to when the action is executed. An example flow would be:
Timelock.signalSetPriceFeed
is called, this specifies the Vault address and the address of the new price feedAt least 24 hours must pass
Timelock.setPriceFeed
can be called, this will update theVault.priceFeed
value
Last updated