UniswapV3PoolPriceAdapter
UniswapV3PoolPriceAdapter
Price adapter for ERC20 spot assets vs USDC using a registered Uniswap V3 pool.
TWAP via pool.observe([TWAP_OBSERVE_SECONDS, 0]); tick mean matches OracleLibrary.consult rounding,
then TickMath.getSqrtRatioAtTick. Failed observe reverts with TwapUnavailable.
setPool probes the same observe horizon and enforces MIN_OBSERVATION_CARDINALITY on slot0 so registration
fails before a pool is stored. Runtime cardinality is not re-checked (buffer size is not freshness).
When MAX_OBSERVATION_STALENESS_SECONDS > 0, the latest oracle observation at slot0.observationIndex must be
initialized and within that age vs block.timestamp at both registration and read (heuristic only).
sqrtPriceX96==0 in slot0 reverts PoolNotInitialized. MIN_POOL_LIQUIDITY checks in-range liquidity() only.
MIN_TWAP_WINDOW
uint32 MIN_TWAP_WINDOW
Minimum allowed TWAP window to avoid effectively-spot pricing.
MAX_ASSET_DECIMALS
uint8 MAX_ASSET_DECIMALS
Maximum IERC20Metadata(asset).decimals() supported for scaling.
PoolNotInitialized
error PoolNotInitialized(address asset)
Pool registered but slot0 sqrt price is zero (uninitialized).
LowLiquidity
error LowLiquidity(address asset)
In-range pool liquidity below minPoolLiquidity.
TwapUnavailable
error TwapUnavailable(address asset)
observe failed (TWAP probe at registration or price read).
AssetDecimalsTooHigh
error AssetDecimalsTooHigh(address asset, uint8 decimals)
Asset decimals exceed MAX_ASSET_DECIMALS.
InsufficientObservationCardinality
error InsufficientObservationCardinality(address asset, uint16 cardinality, uint16 minimum)
slot0 observationCardinality below minimum at registration (buffer capacity only).
ZeroTwapWindow
error ZeroTwapWindow()
TWAP window seconds is zero in pure sqrt helper.
TickOutOfBounds
error TickOutOfBounds()
Mean TWAP tick is outside int24 bounds accepted by TickMath.
OracleObservationNotInitialized
error OracleObservationNotInitialized(address asset)
Latest oracle observation uninitialized or slot index mismatch vs pool expectations.
OracleStale
error OracleStale(address asset)
Latest oracle observation older than MAX_OBSERVATION_STALENESS_SECONDS (when non-zero).
PRICE_DECIMALS
uint8 PRICE_DECIMALS
Extra price precision digits (matches ERC4626PriceAdapter for registry normalization).
USDC
address USDC
Protocol underlying (USDC).
USDC_DECIMALS
uint8 USDC_DECIMALS
Underlying token decimals.
TWAP_OBSERVE_SECONDS
uint32 TWAP_OBSERVE_SECONDS
Deploy-time TWAP horizon in seconds (must be >= MIN_TWAP_WINDOW).
MIN_POOL_LIQUIDITY
uint128 MIN_POOL_LIQUIDITY
Minimum in-range liquidity(); zero skips.
MIN_OBSERVATION_CARDINALITY
uint16 MIN_OBSERVATION_CARDINALITY
Minimum slot0.observationCardinality enforced at registration only (buffer size, not freshness).
MAX_OBSERVATION_STALENESS_SECONDS
uint32 MAX_OBSERVATION_STALENESS_SECONDS
Max seconds since latest observation blockTimestamp; zero disables staleness check.
poolOf
mapping(address => address) poolOf
Registered pool per priced asset (asset/USDC pool).
usdcIsToken0ForAsset
mapping(address => bool) usdcIsToken0ForAsset
Whether USDC is token0 for the asset pool (set in setPool).
PoolSet
event PoolSet(address asset, address pool)
Pool registration updated for an asset.
Parameters
| Name | Type | Description |
|---|---|---|
| asset | address | Priced ERC20 (not USDC). |
| pool | address | Uniswap V3 pool registered for the asset. |
constructor
constructor(address usdc, address initialOwner, uint32 twapObserveSeconds_, uint128 minPoolLiquidity_, uint16 minObservationCardinality_, uint32 maxObservationStalenessSeconds_) public
Constructor
Parameters
| Name | Type | Description |
|---|---|---|
| usdc | address | Protocol underlying (USDC) |
| initialOwner | address | Ownable owner for setPool |
| twapObserveSeconds_ | uint32 | TWAP window in seconds; must be >= MIN_TWAP_WINDOW |
| minPoolLiquidity_ | uint128 | Minimum in-range liquidity; 0 skips |
| minObservationCardinality_ | uint16 | Minimum observation cardinality at setPool; 0 skips |
| maxObservationStalenessSeconds_ | uint32 | Max age of latest observation; 0 skips staleness guard |
setPool
function setPool(address asset, address pool) external
Register or replace the V3 pool used to price an asset.
Pool tokens must be asset and USDC in either order. Probes observe TWAP horizon and staleness.
Parameters
| Name | Type | Description |
|---|---|---|
| asset | address | ERC20 to price (not USDC) |
| pool | address | Uniswap V3 pool address |
validatePriceAdapter
function validatePriceAdapter(address asset) external view
Validates that the given asset is compatible with this adapter
Reverts with InvalidAdapter if the asset is not compatible
Parameters
| Name | Type | Description |
|---|---|---|
| asset | address | The address of the asset to validate |
getPriceData
function getPriceData(address asset) external view returns (uint256 price, uint8 decimals)
Get the price data for an asset
The asset shall be whitelisted in the OrionConfig contract. The registry will handle normalization to priceAdapterDecimals.
Parameters
| Name | Type | Description |
|---|---|---|
| asset | address | The address of the asset to get the price for |
Return Values
| Name | Type | Description |
|---|---|---|
| price | uint256 | The raw price of the asset |
| decimals | uint8 | The number of decimals for the returned price |
_validateObservationFreshness
function _validateObservationFreshness(contract IUniswapV3Pool pool, address asset, uint16 observationIndex) internal view
Heuristic: slot0.observationIndex entry must be initialized and recent when staleness cap is set.
_observeSqrtPriceX96
function _observeSqrtPriceX96(address pool, address asset) internal view returns (uint160 sqrtPriceX96)
TWAP sqrt from observe.
Price uses tick cumulatives; the second observe return is length-checked for ABI sanity.
Parameters
| Name | Type | Description |
|---|---|---|
| pool | address | Uniswap V3 pool used for the asset pair. |
| asset | address | Asset being priced (used in revert errors). |
Return Values
| Name | Type | Description |
|---|---|---|
| sqrtPriceX96 | uint160 | Q64.96 sqrt price derived from TWAP mean tick. |
_priceFromSqrtX96
function _priceFromSqrtX96(uint256 precisionAmount, uint160 sqrtPriceX96, bool usdcIsToken0) internal pure returns (uint256 price)
Convert sqrtPriceX96 to raw USDC per raw asset using PRICE_DECIMALS scaling.
Parameters
| Name | Type | Description |
|---|---|---|
| precisionAmount | uint256 | 10 ** (PRICE_DECIMALS + assetDecimals). |
| sqrtPriceX96 | uint160 | Q64.96 sqrt price from TWAP. |
| usdcIsToken0 | bool | Whether USDC is token0 in the pool. |
Return Values
| Name | Type | Description |
|---|---|---|
| price | uint256 | Raw price in USDC minor units with PRICE_DECIMALS extra precision. |
_sqrtPriceX96FromTickCumulativeDelta
function _sqrtPriceX96FromTickCumulativeDelta(int56 tickCumulativesDelta, uint32 window) internal pure returns (uint160 sqrtPriceX96)
Mean tick from oracle cumulative delta to sqrtPriceX96 (Q64.96).
Parameters
| Name | Type | Description |
|---|---|---|
| tickCumulativesDelta | int56 | Cumulative tick delta between observe endpoints. |
| window | uint32 | TWAP window in seconds. |
Return Values
| Name | Type | Description |
|---|---|---|
| sqrtPriceX96 | uint160 | Q64.96 sqrt price computed from the mean tick. |