Skip to main content

PriceCache

Git Source

Inherits: Policy, PolicyEnabler, IPriceCache, IVersioned

Title: PriceCache

Author: OlympusDAO

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

Permissionless pair cache policy for approved PRICE assets

State Variables

_PRICE_KEYCODE

bytes5 internal constant _PRICE_KEYCODE = "PRICE"

_ROLES_KEYCODE

bytes5 internal constant _ROLES_KEYCODE = "ROLES"

_PRICE_ADMIN_ROLE

bytes32 internal constant _PRICE_ADMIN_ROLE = "price_admin"

_MAX_SYMBOL_LENGTH

uint256 internal constant _MAX_SYMBOL_LENGTH = 32

PRICE

IPRICEv2 public PRICE

_UNIT_OF_ACCOUNT_DECIMALS

uint8 internal immutable _UNIT_OF_ACCOUNT_DECIMALS

_UNIT_OF_ACCOUNT_SYMBOL

bytes32 internal immutable _UNIT_OF_ACCOUNT_SYMBOL

_cacheEpoch

uint256 internal _cacheEpoch

_nonContractAssetMetadata

mapping(address asset => IPriceCache.NonContractAssetMetadata metadata) internal _nonContractAssetMetadata

_assetEpoch

mapping(address asset => uint64 epoch) internal _assetEpoch

_pairSnapshot

mapping(uint256 epoch => mapping(bytes32 key => IPriceCache.PairSnapshot snapshot)) internal _pairSnapshot

Functions

constructor

constructor(Kernel kernel_, uint8 unitOfAccountDecimals_, string memory unitOfAccountSymbol_) Policy(kernel_);

configureDependencies

Define module dependencies for this policy.

Reverts if:

  • The configured PRICE module version is unsupported
  • The configured PRICE module does not implement IPRICEv2
  • The configured ROLES module major version is unsupported
function configureDependencies() external override returns (Keycode[] memory dependencies);

Returns

NameTypeDescription
dependenciesKeycode[]- Keycode array of module dependencies.

requestPermissions

Function called by kernel to set module function permissions.

Does not revert.

function requestPermissions() external pure override returns (Permissions[] memory requests);

Returns

NameTypeDescription
requestsPermissions[]- Array of keycodes and function selectors for requested permissions.

VERSION

Returns the version of the contract

Does not revert.

function VERSION() external pure override returns (uint8, uint8);

Returns

NameTypeDescription
<none>uint8major - Major version upgrade indicates breaking change to the interface.
<none>uint8minor - Minor version change retains backward-compatible interface.

_onlyPriceOrAdminRole

Reverts unless the caller has the price_admin or admin role.

Reverts with PolicyAdmin.NotAuthorised() if the caller lacks both roles.

function _onlyPriceOrAdminRole() internal view;

onlyPriceOrAdminRole

Modifier that reverts unless the caller has the price_admin or admin role.

modifier onlyPriceOrAdminRole() ;

onlyPolicyActive

Reverts if this policy is not active in the Kernel.

modifier onlyPolicyActive() ;

_onlyPolicyActive

function _onlyPolicyActive() internal view;

decimals

Return the USD decimal scale used by cached pair legs

Reverts if dependencies are not configured and the PRICE module is unset.

function decimals() external view override returns (uint8 decimals_);

Returns

NameTypeDescription
decimals_uint8USD decimal scale for cached assetPriceUsd/quotePriceUsd values

assetDecimals

Return the amount decimal scale used for asset_ quote conversion

Reverts if:

  • asset_ is a non-contract asset that is not known to PRICE
  • asset_ is a non-contract asset without registered decimals
function assetDecimals(address asset_) external view override returns (uint8 decimals_);

Parameters

NameTypeDescription
asset_addressAsset identifier

Returns

NameTypeDescription
decimals_uint8Amount decimal scale for asset_

assetSymbol

Return the symbol used for naming and display of asset_

Reverts if:

  • asset_ is a non-contract asset that is not known to PRICE
  • asset_ is a non-contract asset without registered symbol metadata
function assetSymbol(address asset_) external view override returns (string memory symbol_);

Parameters

NameTypeDescription
asset_addressAsset identifier

Returns

NameTypeDescription
symbol_stringSymbol for asset_

setNonContractAssetMetadata

Set the metadata for a registered non-contract asset

Reverts if:

  • The policy is disabled
  • The caller is neither price_admin nor admin
  • asset_ is not a valid non-contract asset managed by PRICE
  • symbol_ is empty or exceeds the configured max length
function setNonContractAssetMetadata(address asset_, uint8 decimals_, string calldata symbol_)
external
override
onlyEnabled
onlyPriceOrAdminRole;

Parameters

NameTypeDescription
asset_addressNon-contract asset identifier
decimals_uint8Amount decimal scale for asset_
symbol_stringDisplay symbol for asset_

removeNonContractAssetMetadata

Remove the configured metadata for a non-contract asset

Reverts if:

  • The policy is disabled
  • The caller is neither price_admin nor admin
  • asset_ is the unit of account
  • asset_ does not have registered metadata
function removeNonContractAssetMetadata(address asset_) external override onlyEnabled onlyPriceOrAdminRole;

Parameters

NameTypeDescription
asset_addressNon-contract asset identifier

cachePrice

Cache an explicit asset/quote pair snapshot

Reverts if:

  • The policy is deactivated in Kernel
  • The policy is disabled
  • The pair is invalid (zero address or identical tokens)
  • Either non-unit asset in the pair is not approved in PRICE
  • PRICE cannot return a current USD price for either token
function cachePrice(address asset_, address quote_) public override onlyPolicyActive onlyEnabled;

Parameters

NameTypeDescription
asset_addressAsset in requested orientation
quote_addressQuote in requested orientation

cachePriceIfNecessary

Cache an explicit pair only when stale for maxAge_

Reverts if:

  • The policy is deactivated in Kernel
  • The policy is disabled
  • Pair validation fails while evaluating staleness
  • PRICE cannot serve required data when a recache is needed
function cachePriceIfNecessary(address asset_, address quote_, uint48 maxAge_)
external
override
onlyPolicyActive
onlyEnabled;

Parameters

NameTypeDescription
asset_addressAsset in requested orientation
quote_addressQuote in requested orientation
maxAge_uint48Maximum acceptable snapshot age in seconds

getCachedPrice

Get the last cached snapshot for a pair in requested orientation

Reverts if:

  • The policy is deactivated in Kernel
  • The policy is disabled
  • The pair is invalid (zero address or identical tokens)
  • Either non-unit asset in the pair is not approved in PRICE
  • Pair decimals validation fails

Returns a fully zeroed CachedPrice when the stored snapshot was invalidated by a later non-contract decimals update or removal for either asset in the pair.

function getCachedPrice(address asset_, address quote_)
public
view
override
onlyPolicyActive
onlyEnabled
returns (CachedPrice memory cachedPrice);

Parameters

NameTypeDescription
asset_addressAsset in requested orientation
quote_addressQuote in requested orientation

Returns

NameTypeDescription
cachedPriceCachedPriceLast cached pair snapshot data; all fields are zero when no snapshot exists

isStale

Return whether pair snapshot is stale for maxAge_

Reverts if:

  • The policy is deactivated in Kernel
  • The policy is disabled
  • Pair validation fails in getCachedPrice
function isStale(address asset_, address quote_, uint48 maxAge_)
public
view
override
onlyPolicyActive
onlyEnabled
returns (bool stale);

Parameters

NameTypeDescription
asset_addressAsset in requested orientation
quote_addressQuote in requested orientation
maxAge_uint48Maximum acceptable snapshot age in seconds

Returns

NameTypeDescription
staleboolTrue when no cache exists or cache is older than maxAge_

_cachePrice

function _cachePrice(address asset_, address quote_) internal;

_getCachedPrice

function _getCachedPrice(address asset_, address quote_) internal view returns (CachedPrice memory cachedPrice);

_isStale

function _isStale(address asset_, address quote_, uint48 maxAge_) internal view returns (bool stale);

_isUnitOfAccount

function _isUnitOfAccount(address asset_) internal view returns (bool);

_validatePair

function _validatePair(address asset_, address quote_) internal view;

_validatePairDecimals

Validate that both legs in a pair have resolvable cache metadata

Reverts if _assetDecimals(asset_) or _assetDecimals(quote_) reverts.

function _validatePairDecimals(address asset_, address quote_) internal view;

Parameters

NameTypeDescription
asset_addressAsset in requested orientation
quote_addressQuote in requested orientation

_assetDecimals

Resolve the amount-decimal scale for an asset identifier

Contract assets source decimals from IERC20.decimals(). Non-contract assets must be known to PRICE and have registered metadata in this cache.

Reverts if:

  • asset_ is a non-contract asset that is not registered in PRICE
  • asset_ is a registered non-contract asset without cache decimals
  • asset_ is a contract whose decimals() call reverts
function _assetDecimals(address asset_) internal view returns (uint8 decimals_);

Parameters

NameTypeDescription
asset_addressAsset identifier

Returns

NameTypeDescription
decimals_uint8Amount-decimal scale for asset_

_assetSymbol

Resolve the symbol for an asset identifier

Contract assets source symbols from IERC20.symbol(). Non-contract assets must be known to PRICE and have registered symbol metadata in this cache.

Reverts if:

  • asset_ is a non-contract asset that is not registered in PRICE
  • asset_ is a registered non-contract asset without cache symbol metadata
  • asset_ is a contract whose symbol() call reverts
function _assetSymbol(address asset_) internal view returns (string memory symbol_);

Parameters

NameTypeDescription
asset_addressAsset identifier

Returns

NameTypeDescription
symbol_stringSymbol for asset_

_isKnownNonContractAsset

Return whether a non-contract asset identifier is known to PRICE

Returns true for PRICE's configured unit of account. All other non-contract assets must be explicitly registered in PRICE.

Reverts if PRICE.unitOfAccount() reverts because dependencies are not configured.

function _isKnownNonContractAsset(address asset_) internal view returns (bool);

Parameters

NameTypeDescription
asset_addressNon-contract asset identifier

Returns

NameTypeDescription
<none>boolbool True if asset_ is known to PRICE

_isConfigurableNonContractAsset

Return whether an asset can have non-contract metadata configured in the cache

This is intended for admin-managed non-contract asset metadata registration paths.

Reverts if _isKnownNonContractAsset(asset_) reverts because PRICE dependencies are not configured.

function _isConfigurableNonContractAsset(address asset_) internal view returns (bool);

Parameters

NameTypeDescription
asset_addressAsset identifier

Returns

NameTypeDescription
<none>boolbool True if asset_ is a non-contract asset known to PRICE

_registerUnitOfAccountMetadataIfMissing

Register the unit-of-account metadata in the cache if it has not been set yet

This is used only during dependency configuration to seed the initial unit-of-account metadata without overwriting a later admin update on replayed configureDependencies().

Reverts if PRICE.unitOfAccount() reverts because the PRICE module is not configured.

function _registerUnitOfAccountMetadataIfMissing() internal;

_validateSymbol

Validate a non-contract asset symbol before it is stored

Reverts if symbol_ is empty or exceeds _MAX_SYMBOL_LENGTH.

function _validateSymbol(string memory symbol_) internal pure;

_stringToBytes32

Convert a <=32 byte string into a bytes32 word for immutable storage

function _stringToBytes32(string memory value_) internal pure returns (bytes32 result_);

_bytes32ToString

Convert a zero-padded bytes32 word back into a string

function _bytes32ToString(bytes32 value_) internal pure returns (string memory result_);

_invalidateAsset

Invalidate cached pairs involving asset_ by advancing its epoch

Use this after changing or removing non-contract asset decimals so future reads treat existing snapshots as uncached.

function _invalidateAsset(address asset_) internal;

Parameters

NameTypeDescription
asset_addressAsset identifier whose cached pairs should be invalidated

_getPriceOrUnit

function _getPriceOrUnit(address asset_) internal view returns (uint256 price_, uint48 timestamp_);

_pairKey

function _pairKey(address asset_, address quote_) internal pure returns (bytes32 key_, bool assetIsToken0_);

supportsInterface

Query if a contract implements an interface

Does not revert.

function supportsInterface(bytes4 interfaceId_) public view virtual override returns (bool);

Parameters

NameTypeDescription
interfaceId_bytes4The interface identifier, as specified in ERC-165

Returns

NameTypeDescription
<none>boolbool True if the contract implements interfaceId_