SharePriceAssertion
Inherits: AccessControlBaseAssertion
Title: SharePriceAssertion
Author: Phylax Systems
Asserts that ERC-4626 vault share prices do not deviate beyond a configurable tolerance, protecting against admin-driven share price manipulation. Invariants covered:
- Share price stability: the ratio totalAssets / totalSupply must not shift more
than
toleranceBpsacross any fork point in the transaction. - Donation attack prevention: catches inflated totalAssets without proportional share minting.
- First-depositor exploit prevention: detects exchange rate manipulation with tiny initial deposits followed by large donations.
- Flash-loan manipulation: flags temporary share price distortion within a transaction.
Uses the V2 assetsMatchSharePrice precompile for a comprehensive all-forks check.
This is a simpler mixin than the full ERC4626SharePriceAssertion – it omits per-call
triggers and focuses on tx-wide share price envelope protection. Use this when the
access-control concern is preventing admin manipulation of share prices, rather than
enforcing full ERC-4626 compliance.
Implementers must override _protectedVaults() to declare which vault addresses and
tolerances to check. Each configured vault produces one all-forks precompile call, so
large vault families should split coverage or move to a batched primitive when one is
available.
Functions
_protectedVaults
Returns the vaults whose share prices must remain stable across the transaction.
Override to declare the protocol-specific vault addresses and tolerances. Tighter tolerances (e.g., 10 bps) are appropriate for stablecoin vaults; wider tolerances (e.g., 50-100 bps) may be needed for volatile-asset vaults or vaults with rebasing underlying assets.
function _protectedVaults() internal view virtual returns (ProtectedVault[] memory vaults);
Returns
| Name | Type | Description |
|---|---|---|
vaults | ProtectedVault[] | Array of (vault, toleranceBps) pairs to protect. |
_registerSharePriceTriggers
Register the default trigger set for share price protection.
Uses registerTxEndTrigger so the check fires once after the transaction completes.
Call this inside your triggers().
function _registerSharePriceTriggers() internal view;
assertSharePrice
Verifies that all protected vault share prices are stable across the transaction.
Uses ph.assetsMatchSharePrice() for each vault, which reads totalAssets() and
totalSupply() at every fork point and checks for deviation beyond the tolerance.
Reverts on the first vault whose share price moved beyond tolerance.
function assertSharePrice() external view;
Errors
SharePriceChanged
error SharePriceChanged(address vault, uint256 toleranceBps);
Structs
ProtectedVault
A vault and its maximum acceptable share-price deviation.
struct ProtectedVault {
/// @notice The ERC-4626 vault address.
address vault;
/// @notice Maximum allowed share price deviation in basis points. 100 = 1%.
uint256 toleranceBps;
}