or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
GMX Price Feed Explainer
The following notes explain the GMX Protocol's price fetching mechanism. The primary aim to convey a sense of the price fetching mechanism and execution flow as it is used by the GMX protocol.
Introduction
The
Vault
is one of the central contracts of the GMX protocol. It allows users to deposit funds into the vault and mints themGLP
tokens. In addition to withdrawing their assets from the vault, users can also swap tokens, short and long (bet on asset prices, whether they will fall or rise) using leverage. Users get liquidated if losses of the position reduce the collateral's value to the point whereposition size / deposited collateral
is more than themax
allowed leverage. This makes asset price fetching very important. Price fetching done through two contracts:VaultPriceFeed
andFastPriceFeed
.Price Calculation Overview
keeper
bots calculate asset prices by averaging the prices of said asset on Binance, Bitfinex and Coinbase. There are two types of keeper bots:Prices submitted from keepers are not used in two cases (i.e., chainlink prices are used instead):
maxDeviationBasisPoints
(currently 1000 so 10%) in which case a spread will be used. See further below.There is also a element called
maxDeviationBasisPoints
(currently 1000 so 10%). This is the historical max deviation of the prices supplied by the keepers from the chainlink price. If the prices supplied by the keeprs deviate by more than 10% from the chainlink price e.g., CL is 100 and keeper price is 111, then a pricing spread would be created: 100 and 111.This pricing spread will then be used as follows:
There are also
Watcher
bots which monitorKeeper
bots for irregular conduct. If it is noticed, thenWatcher
bots can enforece a spread even if the keeper bots are submitting prices that are within max deviation and are not stale.All prices are multiplied by
1e30
or10**30
to increase precision. 1 USD is thus equal to1e30
.Basis points are also used to account for finer movements in prices and values.
10000
is the BPSDivisor, the max spread bps is 50, max adjustment interval is 2 hours and max adjustment bps are 20.There is another contract called
FastPriceFeed
which is used as a secondary price feed. The prices returned from this contract'sgetPrice
function are ones that are submitted by the keeprs and are to be used if there are none of the issues mentioned above which either force use of the chainlink price or the spread.The
maximise
bool is used to return the higher or lower of the spread price.This above is explained below in detail along with the execution steps.
Price Fetching Flow:
Contracts in consideration::
VaultPriceFeed
: 0x2d68011bcA022ed0E474264145F46CC4de96a002FastPriceFeed
: 0x11D62807dAE812a0F1571243460Bf94325F43BB7VaultPriceFeed Relevant State: (31Dec2022)
useV2Pricing
: falseisAmmEnabled
: falseisSecondaryPriceEnabled
: truesecondaryPriceFeed
akaFastPriceFeed
MAX_ADJUSTMENT_INTERVAL
: 2 hours (7200s)MAX_ADJUSTMENT_BASIS_POINTS
: 20 BPS (0.2%)MAX_SPREAD_BASIS_POINTS
: 50 BPS (0.5%)BPS_DIVISOR
: 10000 (100%)maxStrictPriceDeviation
: 10000000000000000000000000000 OR 1e28FastPriceFeed Relevant State: (31Dec2022)
MAX_PRICE_DURATION
: 30 minutes (1800s)priceDuration
: 5 minutes (300s)maxPriceUpdateDelay
: 1 hr (3600s)isSpreadEnabled
: falsespreadBasisPointsIfChainError
: 500 (5%)spreadBasisPointsIfInactive
: 2 (0.2%)maxDeviationBasisPoints
: 1000 (10%)Functions in consideration:
1.
VaultPriceFeed.getPrice(address _token, bool _maximise, bool _includeAmmPrice)
2.
FastPriceFeed.getPrice(address _token, uint256 _refPrice, bool _maximise)
Looking into
getPrice
The following happens when a call to
VaultPriceFeed.getPrice(_token, _maximise, _includeAmmPrice)
is made:getPrimaryPrice(_token, _maximise))
, use the highest/ lowest out of 3 rounds depending on the maximise bool passed.isSecondaryPriceEnabled
is true (it is), use the other contractFastPriceFeed.getPrice(_token,price,maximise)
to calculate and use a price.We now look at
FastPriceFeed.getPrice
where the process goes after step 2. This function is supplied 3 arguments:a. The token address
b. The reference price for the given token as fetched from Chainlink in
VaultPriceFeed.getPrice()
.c. The maximise bool, whether to return the higher or lower price in case a spread is used.
If it has been more than 1 hr since the price was last updated, convert price to BPS (multiply by
BPS_DIVISOR
- 10_000BPS) addspreadBasisPointsIfChainError
(500BPS so 5%) to it and divide by BPS_DIVISOR and this is the price.3.1. If it has not been more than 1 hr since last price update, then if it has been more than
priceDuration
(5 minutes) since the last price update, add / subtractspreadBasisPointsIfInactive
(2 BPS - 0.2%) from the price depending on the maximise bool, and this is the price.If It has NEITHER been 1 hr NOR 5 mins since last price update, calculate the BPS diff b/w refPrice and fastPrice (the stale price from
prices[_token]
for the given token, ).If
favorFastPrice(_token)
returns false for this token (i.e., bool to use the fast price or not. Watcher bots can disable fast price for this token due to any suspicion) OR the diff as calculated in prev step exceeds themaxDeviationBasisPoints
1000 so 10%, then a spread-based (i.e., higher or lower) price will be returned depending on_maximise
. If maximise is true, then the greater ofrefPrice
andfastPrice
will be returned. If maxmimise is false, then the lesser of the two is the price.If
favorFastPrice
returns true for the token and the diff in BPS is within themaxDeviationBasisPoints
threshold, then the price is simply thefastPrice
which isprices[token]
.Control now shifts back to
VaultPriceFeed.getPrice()
as the price calculated thus far byFastPriceFeed.getPrice()
is returned to it.VaultPriceFeed.getPrice()
takes this price and performs further checks and calculations as shown below:If the token is a stablecoin, check how much its price deviates from 1 USD (10**30). If it the difference b/w 1 USD and its price is within the
maxStrictPriceDeviation
(1e28), continue with this price.7.1. If the price is more than 1 USD and maximise is true, return that price. Similarly, if the price is less than 1 USD and maximise is false, continue with this price.
7.2 If the price is neither more than 1 USD nor less than it, continue with 1 USD (1e30) as the price.
If the token is not a stable coin, add/ subtract (depending on maximise bool) the
spreadBasisPoints
for that token(if any have been set) and continue with this price.If the token has any
adjustmentBps
set, then add/ subtract those from the price calculated thus far, depending on if theisAdjustmentAdditive[token]
for this token is additive or subtractive.Return the price to the caller.