Token Oracles

How the token oracles work

The asset prices that help determine the target balances, and the total and individual token values for the Index are obtained via a combination of Chainlink oracles and the GMX Reader contract. These contract calls happen inside getPrice() on each token’s Oracle contract.

constructor

At deployment, the Oracle contract stores the token’s GMX market _symbol, the GMX market address, the market's decimal adjustment used by GMX architecture, the feed address and heartbeat for the asset's Chainlink Price Feed, Chainlink's arbSequencerUptimeFeed, Chainlink's usdcPriceFeed, the gmxDataStore, and the gmxReader. Lastly, it sets msg.sender as the owner (hereafter referred to as Admin).

Parameters:

Name
Type
Description

_symbol

string

The symbol of the Oracle's GM asset

_gmxAssetMarket

address

The address of the GM market token

_assetPriceFeed

address

The address of the long asset's Chainlink price feed

_assetHeartbeat

uint256

The max time interval between updates of the long asset's Chainlink price feed

_decAdjustment

uint256

Decimal adjustment needed for GMX contract logic.

updateSequencerUptimeFeed

function updateSequencerUptimeFeed(address _sequencerUptimeFeed, uint256 _gracePeriod) external onlyOwner

Updates/stores the Chainlink Arbitrum Sequencer Uptime Feed and the desired grace period that must pass after the Sequencer comes back online . Only the Admin can call this function. The Sequencer Uptime Feed address is typecast to the AggregatorV3Interface type. Upon success, the call emits a SequencerFeedUpdated event.

Parameters:

Name
Type
Description

_sequencerUptimeFeed

address

The address for the Chainlink Arbitrum Sequencer Uptime Feed

_gracePeriod

uint256

After the Sequencer comes back online, this period must pass before the Oracle contract can return prices again.

updatePriceFeed

function updatePriceFeed(address _feed, uint256 _heartbeat, uint256 _decAdjust, bool assetIsUSDC) external onlyOwner

Updates/stores the price _feed, _heartbeat, and _decAdjust for one asset of the GM token pair. If the boolean assetIsUSDC is set to true, the function updates the USDC Price Feed, along with its heartbeat. Only the Admin can call this function. The Sequencer Uptime Feed address is typecast to the AggregatorV3Interface type. Upon success, the call emits a PriceFeedUpdated event.

Parameters:

Name
Type
Description

_feed

address

The address of the Chainlink price feed

usdcFeedHeartbeat

uint256

The heartbeat of the Chainlink price feed

_decAdjust

uint256

The decimal adjustment needed for GMX contract logic interaction.

assetIsUSDC

boolean

If true, USDC variables will change. If false, the GM asset's variables will change.

getAssetInfo

function getAssetInfo(bool _isUSDC) external view returns (address, uint256, uint256)

Retrieves the Chainlink price feed address, feed heartbeat, and decimal adjustment for the asset or USDC.

Parameters:

Name
Type
Description

_isUSDC

boolean

true, USDC variables will change. If false, the GM asset's variables will change.

Returns:

Name
Type
Description

assetPriceFeed

address

The address of the Chainlink price feed

usdcFeedHeartbeat

uint256

The heartbeat of the Chainlink price feed

assetDecimalAdjust

uint256

The decimal adjustment needed for GMX contract logic interaction.

getPrice

function getPrice() external view returns (uint256, uint256)

Retrieves the current price of the GM token each specific oracle belongs to.

Before calculating the price, a series of checks must be passed. An internal function calls to the Chainlink Arbitrum Sequencer Uptime Feed to make sure the Sequencer is online. If not, the function call chain reverts.

The call chain proceeds to retrieve both the *asset's price and USDC's price from Chainlink. If either of the prices are stale (the time elapsed since the last price update is greater than the heartbeat interval of the feed), the call chain reverts.

After price decimal adjustments, the call chain retrieves marketProps from the GMX reader by calling the getMarket() function. Finally, getMarketTokenPrice() is called with marketProps pricing, and other necessary variables as arguments to retrieve the token's current price. After a type conversion and another decimal conversion, the final price is returned by the function.

For more info on getMarket() and getMarketTokenPrice(), please see the GMX documentation.

*If the asset is gmUSDC-USDT-SWAP, the call chain includes this _getUSDCUSDTPrice.

Name
Type
Description

price

uint256 (x2)

The price of the GM token, determined by the GMX reader contract

_sequenceUptimeCheck

function _sequencerUptimeCheck() internal view 

This function calls latestRoundData() on the Sequencer Uptime Feed instance to retrieve the latest uptimeAnswer and startedAt. If uptimeAnswer does not equal 0, the Arbitrum Sequencer is down, and the function call reverts. If uptimeAnswer equals 0, then the Arb Sequencer is up. If the sequencer has just gone down, but was started back up, calls made within the sequencerGracePeriod will revert. Once the sequencer has been up for longer than an hour, calls will function normally.

_getUSDCUSDTPrice

function _getUSDCUSDTPrice() internal view returns (uint256, uint256)

After the GMX market token balances of USDC and USDT are obtained, this internal function obtains their prices from Chainlink. The final gmUSDC-USDT-SWAP price is determined as follows:

uint256 price = (usdcBalance * usdcPrice + usdtBalance * usdtPrice) / totalSupply;

where totalSupply is the total supply of gmUSDC-USDT-SWAP market tokens.

Returns:

Name
Type
Description

price

uint256 (x2)

The calculated price of the gmUSDC-USDT-SWAP token.

function _getPriceFromChainlink(AggregatorV3Interface _dataFeed, uint256 _heartbeat) internal view returns (uint256)

This internal function calls latestRoundData() on the price feed instance to retrieve the latest answer and updatedAt time. If updatedAt is less than block.timestamp - usdcFeedHeartbeat, the returned price is considered "stale," and the function will revert.

If the Arbitrum Sequencer is up and the Price Feed price is not stale, the price is returned by the call chain.

Parameters:

Name
Type
Description

_dataFeed

AggregatorV3Interface

The AggregatorV3Interface instance of the Chainlink price feed

_heartbeat

uint256

The max time interval between updates of the asset's Chainlink price feed

Returns:

Name
Type
Description

answer

uint256

The Oracle-returned price of the token. (Returned decimals will vary.)

Last updated