Settlement
Overview
Settlement is the periodic process of recalculating the vault's Net Asset Value (NAV), updating the Price Per Share (PPS), and collecting performance fees. This is a manual, off-chain-triggered operation — PPS does not update automatically on every block.
Access Control
Only the Accountant role may trigger settle(). Only the VaultOwner may call confirmSettlement().
Settlement Flow
sequenceDiagram
actor Acct as Accountant
participant Vault as KingsVault (ETH)
participant Port as KPortfolio
participant Pools as EarnPools (Aave/Morpho)
participant Hyper as HyperStrategy (HyperEVM)
participant Core as HyperCore (L1Read)
Note over Acct,Core: Phase 1: Gather Total Assets
Acct->>Vault: settle()
Vault->>Port: totalValues()
Port->>Pools: valuesOf() for each enabled pool
Pools-->>Port: balance per pool
Port-->>Vault: ETH-side total
Note over Hyper,Core: Phase 1b: Cross-Chain NAV Report
Hyper->>Core: L1Read (0x800) — vaultEquity
Hyper->>Core: L1Read (0x800) — spotBalance
Hyper-->>Vault: CCIP: totalAsset (vaultEquity + spotBalance + EVM idle)
Note over Vault: Phase 2: Compute PPS
Vault->>Vault: TotalAssets = ETH_total + Hyper_total
Vault->>Vault: PPS = TotalAssets / totalSupply()
Note over Vault: Phase 3: Performance Fee
alt PPS > HWM (High Water Mark)
Vault->>Vault: FeeShares = (PPS - HWM) * supply * feeRate / PPS
Vault->>Vault: _mint(Manager, FeeShares)
Vault->>Vault: Update HWM = PPS
end
Vault-->>Acct: Settled PPS
Step-by-Step
Phase 1: Gather Total Assets
| Step | Component | Action | Detail |
|---|---|---|---|
| 1.1 | Accountant | Trigger settlement. | vault.settle() |
| 1.2 | KingsVault | Query ETH-side assets. | Calls portfolio.totalValues() which iterates all enabled EarnPools. |
| 1.3 | KPortfolio | Aggregate pool values. | Sums valuesOf() from each pool + portfolio idle USDC. |
| 1.4 | HyperStrategy | Query HyperCore state. | Reads vaultEquity and spotBalance via L1Read precompile (0x800). |
| 1.5 | HyperStrategy | Report to Ethereum. | Sends totalAsset value back via CCIP ccipSend(). |
| 1.6 | KingsVault | Receive cross-chain report. | _ccipReceive() processes settlement data message. |
Phase 2: Compute PPS
| Step | Action | Formula |
|---|---|---|
| 2.1 | Sum total assets. | TotalAssets = Vault_Idle + Portfolio_Total + HyperCore_Equity + Pending_CCIP |
| 2.2 | Calculate PPS. | PPS = TotalAssets / totalSupply() |
| 2.3 | Default PPS. | If totalSupply() == 0, PPS defaults to 1.000000. |
Phase 3: Performance Fee Collection
Fee is only charged when PPS exceeds the High Water Mark (HWM).
| Step | Action | Formula |
|---|---|---|
| 3.1 | Check profit. | PPS_current > PPS_HWM ? |
| 3.2 | Calculate fee shares. | FeeShares = (PPS_current - PPS_HWM) * TotalSupply * feeRate / PPS_current |
| 3.3 | Mint to Manager. | _mint(ManagerAddress, FeeShares) |
| 3.4 | Update HWM. | PPS_HWM = PPS_current |
Worked Example
Before settlement:
| Parameter | Value |
|---|---|
| TotalSupply | 1,000,000 shares |
| PPS_HWM | 1.10 |
| Fee Rate | 20% |
Settlement data received:
| Parameter | Value |
|---|---|
| TotalAssets | 1,200,000 USDC |
| PPS_current | 1,200,000 / 1,000,000 = 1.20 |
Fee calculation:
- Profit check:
1.20 > 1.10→ profit exists. - Total profit:
(1.20 - 1.10) * 1,000,000 = 100,000 USDC - Fee amount:
100,000 * 20% = 20,000 USDC - Fee shares:
20,000 / 1.20 = 16,666.67 shares - Mint
16,666.67shares to Manager. - Update HWM:
1.20.
After settlement:
| Parameter | Value |
|---|---|
| TotalSupply | 1,016,666.67 shares |
| PPS (post-dilution) | 1,200,000 / 1,016,666.67 ≈ 1.180 |
Dual Confirmation (Stage 1)
In Stage 1, settlement uses a two-step confirmation to guard against data anomalies:
settle()— Accountant triggers NAV calculation and proposes a PPS.confirmSettlement()— VaultOwner reviews the proposed PPS off-chain and confirms it.
This ensures a human review step before the PPS is committed, protecting against oracle failures or compromised data feeds.
Security Considerations
- Stale PPS: If settlement is not run frequently, deposits and withdrawals execute at an outdated price, potentially disadvantaging one side.
- Fee Timing Attack: A compromised Accountant could delay settlement to accumulate more profit before triggering fee collection, or trigger prematurely.
- Cross-Chain Data Integrity: The HyperCore equity reported via CCIP must be validated against the expected
sourceChainSelectorandsenderAddress. A forged settlement message could manipulate PPS. - Bounded Iteration:
totalValues()must iterate over a bounded number of pools to prevent out-of-gas reverts during settlement.