BaseOracleFactory
Inherits: Policy, PolicyEnabler, IOracleFactory, IVersioned, ReentrancyGuard
Title: BaseOracleFactory
Author: OlympusDAO
Abstract base contract for oracle factories with common functionality
Uses ClonesWithImmutableArgs for gas-efficient oracle deployment
Constants
_ROLES_KEYCODE
bytes5 internal constant _ROLES_KEYCODE = "ROLES";
State Variables
priceCache
The pair cache policy
IPriceCache public priceCache;
_tokensToOracle
Mapping from base token to quote token to maxAge to oracle address
mapping(address baseToken => mapping(address quoteToken => mapping(uint48 maxAge => address oracle)))
internal _tokensToOracle;
_oraclePairVariantCounts
Mapping from an ordered base/quote pair to the number of deployed oracle variants
Updated when oracles are created. Factory-level re-enable uses this count to reject unknown pairs before checking whether any deployed variant is enabled.
mapping(bytes32 pairKey => uint256 variantCount) internal _oraclePairVariantCounts;
_enabledOraclePairVariantCounts
Mapping from an ordered base/quote pair to the number of enabled oracle variants
Updated when oracles are created, enabled, or disabled. Factory-level re-enable recaching uses this count to skip pairs that currently have no enabled oracle.
mapping(bytes32 pairKey => uint256 variantCount) internal _enabledOraclePairVariantCounts;
_oracles
Internal array of all deployed oracles
address[] internal _oracles;
isOracle
Mapping to validate deployed oracles
mapping(address => bool) public isOracle;
_oracleToBaseToken
Mapping from oracle to base token
mapping(address oracle => address baseToken) internal _oracleToBaseToken;
_oracleToQuoteToken
Mapping from oracle to quote token
mapping(address oracle => address quoteToken) internal _oracleToQuoteToken;
_oracleToMaxAge
Mapping from oracle to maxAge
mapping(address oracle => uint48 maxAge) internal _oracleToMaxAge;
_isOracleEnabled
Mapping to track if an oracle is enabled
mapping(address => bool) internal _isOracleEnabled;
isCreationEnabled
Whether new oracle creation is enabled
bool public isCreationEnabled;
Functions
constructor
Constructs a new BaseOracleFactory
Reverts if priceCache_ is not a valid IPriceCache policy for this Kernel.
constructor(Kernel kernel_, address priceCache_) Policy(kernel_);
Parameters
| Name | Type | Description |
|---|---|---|
| kernel_ | Kernel | The Kernel address |
| priceCache_ | address | The price cache policy address |
configureDependencies
Define module dependencies for this policy.
Reverts if the configured ROLES module major version is unsupported.
function configureDependencies() external override returns (Keycode[] memory dependencies);
Returns
| Name | Type | Description |
|---|---|---|
| dependencies | Keycode[] | - 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
| Name | Type | Description |
|---|---|---|
| requests | Permissions[] | - Array of keycodes and function selectors for requested permissions. |
VERSION
Returns the version of the contract
Does not revert.
function VERSION() external pure virtual override returns (uint8 major, uint8 minor);
Returns
| Name | Type | Description |
|---|---|---|
| major | uint8 | - Major version upgrade indicates breaking change to the interface. |
| minor | uint8 | - Minor version change retains backward-compatible interface. |
onlyPolicyActive
Reverts if this policy is not active in the Kernel.
modifier onlyPolicyActive();
_onlyPolicyActive
function _onlyPolicyActive() internal view;
_onlyOracleManagerOrAdminRole
Checks if the caller has the oracle_manager or admin role
function _onlyOracleManagerOrAdminRole() internal view;
_onlyOracleManagerOrAdminOrEmergencyRole
Checks if the caller has the oracle_manager, admin, or emergency role
function _onlyOracleManagerOrAdminOrEmergencyRole() internal view;
onlyOracleManagerOrAdminRole
Modifier that reverts if the caller does not have the oracle_manager or admin role
modifier onlyOracleManagerOrAdminRole();
onlyOracleManagerOrAdminOrEmergencyRole
Modifier that reverts if the caller does not have the oracle_manager, admin, or emergency role
modifier onlyOracleManagerOrAdminOrEmergencyRole();
_getOracleImplementation
Returns the oracle implementation address for cloning
function _getOracleImplementation() internal view virtual returns (address);
Returns
| Name | Type | Description |
|---|---|---|
| <none> | address | address The address of the oracle implementation contract to be cloned |
_encodeOracleData
Encodes oracle-specific data for cloning
This function should perform service-specific validation, calculate parameters, and encode the immutable args for the clone
function _encodeOracleData(
address baseToken_,
address quoteToken_,
uint48 maxAge_,
bytes calldata customParams_
) internal view virtual returns (bytes memory);
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | The base token address |
| quoteToken_ | address | The quote token address |
| maxAge_ | uint48 | The maximum age (in seconds) of cached prices used by the oracle |
| customParams_ | bytes | Service-specific custom parameters (can be empty) |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes | bytes The encoded bytes for cloning |
createOracle
Creates a new oracle for a base/quote token pair
Creates an enabled oracle only after the initial cache write succeeds.
Reverts if:
- The factory is disabled
- The caller is not admin or oracle manager
- Oracle creation is disabled
- An oracle for
(baseToken_, quoteToken_, maxAge_)already exists - Either token is the zero address or both tokens are the same
- Service-specific validation in
_encodeOracleDatafails - Initial cache population fails in the configured price cache policy
function createOracle(
address baseToken_,
address quoteToken_,
uint48 maxAge_,
bytes calldata customParams_
)
external
override
onlyEnabled
onlyOracleManagerOrAdminRole
nonReentrant
returns (address oracle);
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | The base token address |
| quoteToken_ | address | The quote token address |
| maxAge_ | uint48 | The maximum age (in seconds) of cached prices used by the oracle |
| customParams_ | bytes | Service-specific custom parameters (can be empty) |
Returns
| Name | Type | Description |
|---|---|---|
| oracle | address | The address of the created oracle |
getOracle
Gets the oracle address for a base/quote token pair
Does not revert.
function getOracle(
address baseToken_,
address quoteToken_,
uint48 maxAge_
) external view override returns (address oracle);
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | The base token address |
| quoteToken_ | address | The quote token address |
| maxAge_ | uint48 | The maximum age (in seconds) of cached prices used by the oracle |
Returns
| Name | Type | Description |
|---|---|---|
| oracle | address | The address of the oracle, or address(0) if not found |
getPriceCache
Gets the configured price cache policy
Does not revert.
function getPriceCache() external view override returns (address);
Returns
| Name | Type | Description |
|---|---|---|
| <none> | address | The price cache policy address |
getOracles
Gets all deployed oracle addresses
Does not revert.
function getOracles() external view override returns (address[] memory);
Returns
| Name | Type | Description |
|---|---|---|
| <none> | address[] | Array of all oracle addresses |
enableCreation
Enables oracle creation
Reverts if:
- The factory is disabled
- The caller is not admin or oracle manager
- Creation is already enabled
function enableCreation()
external
override
onlyEnabled
onlyOracleManagerOrAdminRole
nonReentrant;
disableCreation
Disables oracle creation
Reverts if:
- The factory is disabled
- The caller is not admin, oracle manager, or emergency
- Creation is already disabled
function disableCreation()
external
override
onlyEnabled
onlyOracleManagerOrAdminOrEmergencyRole
nonReentrant;
setPriceCache
Sets the configured price cache policy
Reverts if:
- The factory is disabled
- The caller is not admin
policy_is zero, not IPriceCache-compatible, or bound to a different Kernel
function setPriceCache(
address policy_
) external override onlyEnabled onlyAdminRole nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
| policy_ | address | The price cache policy address |
enableOracle
Enables a specific oracle
Refreshes the oracle pair cache if stale before marking the oracle enabled.
Reverts if:
- The caller does not have the required role
- The contract is disabled
- The oracle is not created by the factory
- The oracle is already enabled
function enableOracle(
address oracle_
) external override onlyEnabled onlyOracleManagerOrAdminRole nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | The oracle address to enable |
disableOracle
Disables a specific oracle
Decrements the enabled variant count for the oracle pair so factory-level re-enable skips the pair when no enabled variants remain.
Reverts if:
- The caller does not have the required role
- The contract is disabled
- The oracle is not created by the factory
- The oracle is already disabled
function disableOracle(
address oracle_
) external override onlyEnabled onlyOracleManagerOrAdminOrEmergencyRole nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | The oracle address to disable |
isOracleEnabled
Reverts if:
- The policy is deactivated in Kernel
Determines if a given oracle is enabled, using the following logic:
- Factory must be enabled
- Oracle must be created by the factory
- Oracle must be enabled
function isOracleEnabled(
address oracle_
) external view override onlyPolicyActive returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | The oracle address to check |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool | True if the oracle is enabled, false otherwise |
getOracleContext
Checks if a factory-created oracle is enabled and returns the configured price cache
Reverts if:
- The policy is deactivated in Kernel
oracle_was not created by this factory
function getOracleContext(
address oracle_
) external view override onlyPolicyActive returns (bool enabled, address policy);
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | The oracle address to check |
Returns
| Name | Type | Description |
|---|---|---|
| enabled | bool | True if the oracle is enabled, false otherwise |
| policy | address | The configured price cache policy address |
cachePrice
Caches the provided base/quote pair
Reverts if:
- The policy is deactivated in Kernel
- The factory is disabled
- The caller is not a factory-created oracle
- The caller oracle is disabled
(baseToken_, quoteToken_)does not match the caller oracle pair- Underlying cache write fails
function cachePrice(
address baseToken_,
address quoteToken_
) external override onlyPolicyActive onlyEnabled nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | The base token address |
| quoteToken_ | address | The quote token address |
cachePriceIfNecessary
Caches the provided base/quote pair only when stale
Reverts if:
- The policy is deactivated in Kernel
- The factory is disabled
- The caller is not a factory-created oracle
- The caller oracle is disabled
(baseToken_, quoteToken_)does not match the caller oracle pair- Underlying cache evaluation/write fails
function cachePriceIfNecessary(
address baseToken_,
address quoteToken_
) external override onlyPolicyActive onlyEnabled nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | The base token address |
| quoteToken_ | address | The quote token address |
_cacheOraclePrices
Caches prices for the configured oracle token pair
function _cacheOraclePrices(address oracle_) internal;
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | The oracle whose base/quote tokens should be cached |
_cachePriceIfNecessary
Conditionally caches prices for the token pair based on direct pair staleness
function _cachePriceIfNecessary(
address oracle_,
address baseToken_,
address quoteToken_
) internal;
Parameters
| Name | Type | Description |
|---|---|---|
| oracle_ | address | |
| baseToken_ | address | |
| quoteToken_ | address |
_enable
_enable optionally re-caches caller-specified direct pairs from enableData_
before the factory-level isEnabled flag flips back to true. enableData_ can
be empty for a no-op. Pairs with deployed variants are recached only when at
least one variant is currently enabled; disabled oracles validate and refresh
their own pair cache when individually re-enabled.
When enableData_ is non-empty, it must encode:
(address[] baseTokens, address[] quoteTokens).
Reverts if enableData_ is non-empty and:
enableData_cannot be decoded into(address[] baseTokens, address[] quoteTokens)- The decoded base and quote token arrays have different lengths
- A requested pair has no deployed oracle variant for that exact ordering
- The price cache rejects a requested pair that has an enabled oracle variant
function _enable(bytes calldata enableData_) internal virtual override;
Parameters
| Name | Type | Description |
|---|---|---|
| enableData_ | bytes | Custom data that can be used by the implementation. The format of this data is left to the discretion of the implementation. |
_hasOracleVariant
Returns whether the factory has a deployed oracle for the provided pair.
function _hasOracleVariant(bytes32 pairKey_) internal view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| pairKey_ | bytes32 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_hasEnabledOracleVariant
Returns whether the factory has an enabled oracle for the provided pair.
function _hasEnabledOracleVariant(bytes32 pairKey_) internal view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| pairKey_ | bytes32 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_oraclePairKey
Returns the storage key for an ordered oracle base/quote pair.
function _oraclePairKey(
address baseToken_,
address quoteToken_
) internal pure returns (bytes32);
Parameters
| Name | Type | Description |
|---|---|---|
| baseToken_ | address | |
| quoteToken_ | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes32 |
_setPriceCache
function _setPriceCache(address policy_) internal;
Parameters
| Name | Type | Description |
|---|---|---|
| policy_ | address |
_implementsIPriceCache
function _implementsIPriceCache(address policy_) internal view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| policy_ | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_hasSameKernel
function _hasSameKernel(address policy_) internal view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| policy_ | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_validateCachingCaller
function _validateCachingCaller(address caller_) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
| caller_ | address |
_validateCachingPair
function _validateCachingPair(
address caller_,
address baseToken_,
address quoteToken_
) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
| caller_ | address | |
| baseToken_ | address | |
| quoteToken_ | address |
supportsInterface
Query if a contract implements an interface
Does not revert.
function supportsInterface(bytes4 interfaceId_) public view virtual override returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
| interfaceId_ | bytes4 | The interface identifier, as specified in ERC-165 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool | bool True if the contract implements interfaceId_ and false otherwise |