PriceAndFeeCalculator

Inherits: IPriceAndFeeCalculator, BaseFeeCalculator, HasNumeraire

Calculates and manages unit price and fees for multiple vaults that share the same numeraire token. Acts as a price oracle and fee accrual engine. Vault registration workflow is:

  1. Register a new vault with registerVault()

  2. Set the thresholds for the vault with setThresholds()

  3. Set the initial price state with setInitialPrice() Once registered, a vault can have its price updated by an authorized entity. Vault owners set thresholds for price changes, update intervals, and price age. If a price update violates thresholds (too large change, too soon, or too old), the vault is paused. Paused vaults dont accrue fees and cannot have their price updated until they are unpaused by the vault owner. Accrues fees on each price update, based on TVL and performance since last update Supports conversion between vault units, tokens, and numeraire for deposits/withdrawals. All logic and state is per-vault, supporting many vaults in parallel. Only vault owners can set thresholds pause/unpause their vaults, whereas accountants can also pause their vaults Integrates with an external oracle registry for token price conversions

State Variables

ORACLE_REGISTRY

Oracle registry contract for price feeds

IOracleRegistry public immutable ORACLE_REGISTRY;

_vaultPriceStates

Mapping of vault addresses to their state information

mapping(address vault => VaultPriceState vaultPriceState) internal _vaultPriceStates;

Functions

requiresVaultAuthOrAccountant

modifier requiresVaultAuthOrAccountant(address vault);

constructor

constructor(IERC20 numeraire, IOracleRegistry oracleRegistry, address owner_, Authority authority_)
    BaseFeeCalculator(owner_, authority_)
    HasNumeraire(address(numeraire));

registerVault

Register a new vault with the fee calculator

function registerVault() external override;

setInitialPrice

Set the initial price state for the vault

function setInitialPrice(address vault, uint128 price, uint32 timestamp) external requiresVaultAuth(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

price

uint128

New unit price

timestamp

uint32

Timestamp when the price was measured

setThresholds

Set vault thresholds

function setThresholds(
    address vault,
    uint16 minPriceToleranceRatio,
    uint16 maxPriceToleranceRatio,
    uint16 minUpdateIntervalMinutes,
    uint8 maxPriceAge,
    uint8 maxUpdateDelayDays
) external requiresVaultAuth(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

minPriceToleranceRatio

uint16

Minimum ratio (of a price decrease) in basis points

maxPriceToleranceRatio

uint16

Maximum ratio (of a price increase) in basis points

minUpdateIntervalMinutes

uint16

The minimum interval between updates in minutes

maxPriceAge

uint8

Max delay between when a vault was priced and when the price is acceptable

maxUpdateDelayDays

uint8

Max delay between two price updates

setUnitPrice

Set the unit price for the vault in numeraire terms

function setUnitPrice(address vault, uint128 price, uint32 timestamp) external onlyVaultAccountant(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

price

uint128

New unit price

timestamp

uint32

Timestamp when the price was measured

pauseVault

Pause the vault

function pauseVault(address vault) external requiresVaultAuthOrAccountant(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

unpauseVault

Unpause the vault

MUST revert if price or timestamp don't exactly match last update

function unpauseVault(address vault, uint128 price, uint32 timestamp) external requiresVaultAuth(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

price

uint128

Expected price of the last update

timestamp

uint32

Expected timestamp of the last update

resetHighestPrice

Resets the highest price for a vault to the current price

function resetHighestPrice(address vault) external requiresVaultAuth(vault);

Parameters

Name
Type
Description

vault

address

Address of the vault

convertUnitsToToken

Convert units to token amount

function convertUnitsToToken(address vault, IERC20 token, uint256 unitsAmount)
    external
    view
    returns (uint256 tokenAmount);

Parameters

Name
Type
Description

vault

address

Address of the vault

token

IERC20

Address of the token

unitsAmount

uint256

Amount of units

Returns

Name
Type
Description

tokenAmount

uint256

Amount of tokens

convertUnitsToTokenIfActive

Convert units to token amount if vault is not paused

MUST revert if vault is paused

function convertUnitsToTokenIfActive(address vault, IERC20 token, uint256 unitsAmount, Math.Rounding rounding)
    external
    view
    returns (uint256 tokenAmount);

Parameters

Name
Type
Description

vault

address

Address of the vault

token

IERC20

Address of the token

unitsAmount

uint256

Amount of units

rounding

Math.Rounding

The rounding mode

Returns

Name
Type
Description

tokenAmount

uint256

Amount of tokens

convertUnitsToNumeraire

Convert units to numeraire token amount

function convertUnitsToNumeraire(address vault, uint256 unitsAmount) external view returns (uint256);

Parameters

Name
Type
Description

vault

address

Address of the vault

unitsAmount

uint256

Amount of units

Returns

Name
Type
Description

<none>

uint256

numeraireAmount Amount of numeraire

convertTokenToUnits

Convert token amount to units

function convertTokenToUnits(address vault, IERC20 token, uint256 tokenAmount)
    external
    view
    returns (uint256 unitsAmount);

Parameters

Name
Type
Description

vault

address

Address of the vault

token

IERC20

Address of the token

tokenAmount

uint256

Amount of tokens

Returns

Name
Type
Description

unitsAmount

uint256

Amount of units

convertTokenToUnitsIfActive

Convert token amount to units if vault is not paused

MUST revert if vault is paused

function convertTokenToUnitsIfActive(address vault, IERC20 token, uint256 tokenAmount, Math.Rounding rounding)
    external
    view
    returns (uint256 unitsAmount);

Parameters

Name
Type
Description

vault

address

Address of the vault

token

IERC20

Address of the token

tokenAmount

uint256

Amount of tokens

rounding

Math.Rounding

The rounding mode

Returns

Name
Type
Description

unitsAmount

uint256

Amount of units

getVaultState

Return the state of the vault

function getVaultState(address vault) external view returns (VaultPriceState memory, VaultAccruals memory);

Parameters

Name
Type
Description

vault

address

Address of the vault

Returns

Name
Type
Description

<none>

VaultPriceState

vaultPriceState The price state of the vault

<none>

VaultAccruals

vaultAccruals The accruals state of the vault

getVaultsPriceAge

Returns the age of the last submitted price for a vault

function getVaultsPriceAge(address vault) external view returns (uint256);

Parameters

Name
Type
Description

vault

address

Address of the vault

Returns

Name
Type
Description

<none>

uint256

priceAge The difference between block.timestamp and vault's unit price timestamp

isVaultPaused

Check if a vault is paused

function isVaultPaused(address vault) external view returns (bool);

Parameters

Name
Type
Description

vault

address

The address of the vault

Returns

Name
Type
Description

<none>

bool

True if the vault is paused, false otherwise

previewFees

function previewFees(address vault, uint256 feeTokenBalance) external view override returns (uint256, uint256);

_accrueFees

Accrues fees for a vault

It is assumed that validation has already been done Tvl is calculated as the product of the minimum of the current and last price and the minimum of the current and last total supply. This is to minimize potential issues with price spikes

function _accrueFees(address vault, uint256 price, uint256 timestamp) internal;

Parameters

Name
Type
Description

vault

address

The address of the vault

price

uint256

The price of a single vault unit

timestamp

uint256

The timestamp of the price update

_setVaultPaused

Sets the paused state for a vault

function _setVaultPaused(VaultPriceState storage vaultPriceState, address vault, bool paused) internal;

Parameters

Name
Type
Description

vaultPriceState

VaultPriceState

The storage pointer to the vault's price state

vault

address

The address of the vault

paused

bool

The new paused state

_convertTokenToUnits

Converts a token amount to units

function _convertTokenToUnits(
    address vault,
    IERC20 token,
    uint256 tokenAmount,
    uint256 unitPrice,
    Math.Rounding rounding
) internal view returns (uint256 unitsAmount);

Parameters

Name
Type
Description

vault

address

The address of the vault

token

IERC20

The token to convert

tokenAmount

uint256

The amount of tokens to convert

unitPrice

uint256

The price of a single vault unit

rounding

Math.Rounding

The rounding direction

Returns

Name
Type
Description

unitsAmount

uint256

The amount of units

_convertUnitsToToken

Converts a units amount to tokens

function _convertUnitsToToken(
    address vault,
    IERC20 token,
    uint256 unitsAmount,
    uint256 unitPrice,
    Math.Rounding rounding
) internal view returns (uint256 tokenAmount);

Parameters

Name
Type
Description

vault

address

The address of the vault

token

IERC20

The token to convert

unitsAmount

uint256

The amount of units to convert

unitPrice

uint256

The price of a single vault unit

rounding

Math.Rounding

The rounding direction

Returns

Name
Type
Description

tokenAmount

uint256

The amount of tokens

_validatePriceUpdate

Validates a price update

Price is invalid if it is 0, before the last update, in the future, or if the price age is stale

function _validatePriceUpdate(VaultPriceState storage vaultPriceState, uint256 price, uint256 timestamp)
    internal
    view;

Parameters

Name
Type
Description

vaultPriceState

VaultPriceState

The storage pointer to the vault's price state

price

uint256

The price of a single vault unit

timestamp

uint256

The timestamp of the price update

_shouldPause

Determines if a price update should pause the vault

Vault should pause if the price increase or decrease is too large, or if the min update interval has not passed

function _shouldPause(VaultPriceState storage state, uint256 price, uint32 timestamp) internal view returns (bool);

Parameters

Name
Type
Description

state

VaultPriceState

The storage pointer to the vault's price state

price

uint256

The price of a single vault unit

timestamp

uint32

The timestamp of the price update

Returns

Name
Type
Description

<none>

bool

shouldPause True if the price update should pause the vault, false otherwise

Last updated