Skip to main content

UniswapV3Price

Git Source

Inherits: PriceSubmodule

Title: UniswapV3Price

Author: 0xJem

forge-lint: disable-start(mixed-case-function)

Provides prices derived from the TWAP of a Uniswap V3 pool

State Variables

BASE_10_MAX_EXPONENT

The maximum number of decimals allowed for a token in order to prevent overflows

uint8 internal constant BASE_10_MAX_EXPONENT = 30

POOL_PARAMS_LENGTH

The expected length of the encoded pool parameters (address + uint32 = 64 bytes)

uint256 internal constant POOL_PARAMS_LENGTH = 64

POOL_ADDRESS_LENGTH

The expected length of the encoded pool address (32 bytes)

uint256 internal constant POOL_ADDRESS_LENGTH = 32

MIN_TICK

The minimum tick that can be used in a pool, as defined by UniswapV3 libraries

int24 internal constant MIN_TICK = -887272

MAX_TICK

The maximum tick that can be used in a pool, as defined by UniswapV3 libraries

int24 internal constant MAX_TICK = -MIN_TICK

AVERAGE_BLOCK_TIME_SECONDS

Assumed average block time used to estimate required observations for TWAP

uint32 public immutable AVERAGE_BLOCK_TIME_SECONDS

UNISWAP_V3_FACTORY

Canonical Uniswap V3 factory used for pool validation

address public immutable UNISWAP_V3_FACTORY

Functions

constructor

Initializes the submodule and records the assumed block time for TWAP cardinality checks.

Calls the Submodule(parent_) constructor to bind this feed to the parent PRICE module. This function will revert if:

  • averageBlockTimeSeconds_ == 0 (UniswapV3_AverageBlockTimeInvalid)
  • uniswapV3Factory_ == address(0) (UniswapV3_FactoryInvalid) Stores averageBlockTimeSeconds_ in AVERAGE_BLOCK_TIME_SECONDS, which is used by _checkObservationCardinality to compute minimum required pool cardinality.
constructor(Module parent_, uint32 averageBlockTimeSeconds_, address uniswapV3Factory_) Submodule(parent_);

Parameters

NameTypeDescription
parent_ModuleThe PRICE module
averageBlockTimeSeconds_uint32The average block time used for cardinality checks
uniswapV3Factory_addressThe canonical Uniswap V3 factory

SUBKEYCODE

20 byte identifier for the submodule. First 5 bytes must match PARENT().

function SUBKEYCODE() public pure override returns (SubKeycode);

VERSION

function VERSION() public pure override returns (uint8 major, uint8 minor);

getTokenTWAP

Obtains the price of lookupToken_ in USD, using the TWAP from the specified Uniswap V3 oracle.

This function will revert if:

  • The value of params.observationWindowSeconds is less than UniswapV3OracleHelper.TWAP_MIN_OBSERVATION_WINDOW
  • Any token decimals or outputDecimals_ are high enough to cause an overflow
  • Any tokens in the pool are not set
  • lookupToken_ is not in the pool
  • The calculated time-weighted tick is outside the bounds of int24 NOTE: as a UniswapV3 pool can be manipulated using multi-block MEV, the TWAP values can also be manipulated. Price feeds are a preferred source of price data. Use this function with caution. See https://chainsecurity.com/oracle-manipulation-after-merge/
function getTokenTWAP(address lookupToken_, uint8 outputDecimals_, bytes calldata params_)
external
view
returns (uint256);

Parameters

NameTypeDescription
lookupToken_addressThe token to determine the price of.
outputDecimals_uint8The number of output decimals (assumed to be the same as PRICE decimals)
params_bytesPool parameters of type UniswapV3Params

Returns

NameTypeDescription
<none>uint256uint256 Price in the scale of outputDecimals_

getTokenPrice

Obtains the price of lookupToken_ in USD, using the current Slot0 price from the specified Uniswap V3 oracle.

This function will revert if:

  • Any token decimals or outputDecimals_ are high enough to cause an overflow
  • Any tokens in the pool are not set
  • lookupToken_ is not in the pool NOTE: as a UniswapV3 pool can be manipulated using multi-block MEV, the TWAP values can also be manipulated. Price feeds are a preferred source of price data. Use this function with caution. See https://chainsecurity.com/oracle-manipulation-after-merge/
function getTokenPrice(address lookupToken_, uint8 outputDecimals_, bytes calldata params_)
external
view
returns (uint256);

Parameters

NameTypeDescription
lookupToken_addressThe token to determine the price of.
outputDecimals_uint8The number of output decimals (assumed to be the same as PRICE decimals)
params_bytesEncoded Uniswap V3 pool address (32 bytes)

Returns

NameTypeDescription
<none>uint256uint256 Price in the scale of outputDecimals_

_checkPoolAndTokenParams

Performs checks to ensure that the pool, the tokens, and the decimals are valid.

This function will revert if:

  • Any token decimals or outputDecimals_ are high enough to cause an overflow
  • Any tokens in the pool are not set
  • lookupToken_ is not in the pool
function _checkPoolAndTokenParams(address lookupToken_, uint8 outputDecimals_, IUniswapV3Pool pool_)
internal
view
returns (address, uint8, uint8);

Parameters

NameTypeDescription
lookupToken_addressThe token to determine the price of
outputDecimals_uint8The decimals of baseToken
pool_IUniswapV3PoolThe Uniswap V3 pool to use

Returns

NameTypeDescription
<none>addressaddress Quote token
<none>uint8uint8 Quote token decimals
<none>uint8uint8 Lookup token decimals

_checkObservationCardinality

Validates the observation cardinality for a TWAP window.

Uses AVERAGE_BLOCK_TIME_SECONDS to derive the minimum cardinality required to service the requested lookback window. This function will revert if:

  • Pool observation cardinality is below the minimum required cardinality (UniswapV3_ObservationCardinalityInsufficient)
function _checkObservationCardinality(IUniswapV3Pool pool_, uint32 observationWindowSeconds_) internal view;

Parameters

NameTypeDescription
pool_IUniswapV3PoolThe pool used for the TWAP lookup
observationWindowSeconds_uint32The requested observation window in seconds

Errors

UniswapV3_ParamsInvalid

The provided parameters are invalid

error UniswapV3_ParamsInvalid(bytes params_);

Parameters

NameTypeDescription
params_bytesThe encoded parameters

UniswapV3_AssetDecimalsOutOfBounds

The decimals of the asset are out of bounds

error UniswapV3_AssetDecimalsOutOfBounds(address asset_, uint8 assetDecimals_, uint8 maxDecimals_);

Parameters

NameTypeDescription
asset_addressThe address of the asset
assetDecimals_uint8The number of decimals of the asset
maxDecimals_uint8The maximum number of decimals allowed

UniswapV3_LookupTokenNotFound

The lookup token was not found in the pool

error UniswapV3_LookupTokenNotFound(address pool_, address asset_);

Parameters

NameTypeDescription
pool_addressThe address of the pool
asset_addressThe address of the asset

UniswapV3_OutputDecimalsOutOfBounds

The output decimals are out of bounds

error UniswapV3_OutputDecimalsOutOfBounds(uint8 outputDecimals_, uint8 maxDecimals_);

Parameters

NameTypeDescription
outputDecimals_uint8The number of decimals of the output
maxDecimals_uint8The maximum number of decimals allowed

UniswapV3_ParamsPoolInvalid

The pool specified in the parameters is invalid

error UniswapV3_ParamsPoolInvalid(uint8 paramsIndex_, address pool_);

Parameters

NameTypeDescription
paramsIndex_uint8The index of the parameter
pool_addressThe address of the pool

UniswapV3_PoolTokensInvalid

The pool tokens are invalid

error UniswapV3_PoolTokensInvalid(address pool_, uint8 tokenIndex_, address token_);

Parameters

NameTypeDescription
pool_addressThe address of the pool
tokenIndex_uint8The index of the token
token_addressThe address of the token

UniswapV3_PoolTypeInvalid

The pool is invalid

This is triggered if the pool reverted when called, and indicates that the feed address is not a UniswapV3 pool.

error UniswapV3_PoolTypeInvalid(address pool_);

Parameters

NameTypeDescription
pool_addressThe address of the pool

UniswapV3_FactoryInvalid

The provided Uniswap V3 factory is invalid

error UniswapV3_FactoryInvalid(address factory_);

Parameters

NameTypeDescription
factory_addressThe configured factory address

UniswapV3_PoolFactoryInvalid

The pool does not match the canonical Uniswap V3 factory's registered pool

error UniswapV3_PoolFactoryInvalid(address pool_, address expectedPool_, address factory_);

Parameters

NameTypeDescription
pool_addressThe provided pool address
expectedPool_addressThe pool returned by the canonical Uniswap V3 factory
factory_addressThe canonical Uniswap V3 factory

UniswapV3_ObservationCardinalityInsufficient

The pool has insufficient observation cardinality for the TWAP window

error UniswapV3_ObservationCardinalityInsufficient(
address pool_, uint16 observationCardinality_, uint32 observationWindow_, uint32 minimumCardinality_
);

Parameters

NameTypeDescription
pool_addressThe address of the pool
observationCardinality_uint16Current observation cardinality on the pool
observationWindow_uint32Requested TWAP observation window in seconds
minimumCardinality_uint32Minimum cardinality required for the observation window

UniswapV3_AverageBlockTimeInvalid

The configured average block time is invalid

error UniswapV3_AverageBlockTimeInvalid(uint32 averageBlockTimeSeconds_);

Parameters

NameTypeDescription
averageBlockTimeSeconds_uint32The configured average block time in seconds

UniswapV3_PoolReentrancy

Triggered if pool_ is locked, which indicates re-entrancy

error UniswapV3_PoolReentrancy(address pool_);

Parameters

NameTypeDescription
pool_addressThe address of the affected Uniswap V3 pool

Structs

UniswapV3Params

The parameters for a Uniswap V3 pool

struct UniswapV3Params {
IUniswapV3Pool pool;
uint32 observationWindowSeconds;
}

Properties

NameTypeDescription
poolIUniswapV3PoolThe address of the pool
observationWindowSecondsuint32The length of the TWAP observation window in seconds