Multi-Vault Staking Runtime Flow
Signed quotes are active on Base since 17 October 2026. See Signed Quotes in Production for verified bindings, transaction wrappers and emergency-mode limits.
This note describes the current vaultId-based runtime behavior for staking, minting, redemption, and hedger liquidity flows.
Core Runtime State
QuantillonVault tracks:
defaultStakingVaultIdstakingVaultAdapterById[vaultId]stakingVaultActiveById[vaultId]redemptionPriorityVaultIds[]stQEUROTokenByVaultId[vaultId]principalUsdcByVaultId[vaultId]totalUsdcHeldtotalUsdcInExternalVaults
Mint and Stake Flows
The conversion selectors below are inner operations. In production signed mode, submit the permitted operation through executeWithQuote(bytes,bytes) with its exact authorization; bare unquoted conversion calls are rejected.
1) Mint (default routing)
mintQEURO(usdcAmount, minQeuroOut)calls internal mint flow withdefaultStakingVaultId.- If default vault id is non-zero and valid, net USDC is auto-deployed to that vault adapter.
- If default vault id is
0, net USDC remains intotalUsdcHeld.
2) Mint (explicit vault)
mintQEUROToVault(usdcAmount, minQeuroOut, vaultId)uses providedvaultId.
3) Mint + Stake (one-step)
mintAndStakeQEURO(usdcAmount, minQeuroOut, vaultId, minStQEUROOut):- Mints QEURO via the same vault-aware mint flow.
- Resolves
stQEUROTokenByVaultId[vaultId]. - Stakes and transfers stQ token to caller.
Auto-deploy implementation
_mintQEUROCommitmoves net amount from held balance to per-vault principal accounting whentargetVaultId != 0._autoDeployToVault(vaultId, usdcAmount)deposits through configured adapter and emitsUsdcDeployedToExternalVault.
Yield Distribution to Stakers
QuantillonVault 1.6.0 preserves the allocation introduced in 1.5.0 and allocates realized strategy yield by the harvest-time ratio of raw staked QEURO to total QEURO supply. Stakers receive their gross allocation after the configured haircut; treasury receives the unstaked allocation. The hedger receives only that haircut, with no base allocation for hedger collateral. There is no additional staking yield fee on vault credits; conversion costs and admission checks remain.
The release accepts one funded strategy and one outstanding staking series; registered empty strategies are allowed. It rejects unsupported simultaneous allocation. Raw staked QEURO includes unvested credit, while totalAssets() excludes yield not yet redeemable. Shareholders participate pro rata as yield vests; this does not make allocation time-weighted.
The keeper reads yieldDistributionConfig and the on-chain preview. hedgerBase remains zero for ABI compatibility. Older 1.4.x and legacy deployments retain their own models. See Yield Distribution 1.5.0.
Redemption Flow
redeemQEURO(qeuroAmount, minUsdcOut) (normal mode):
- Computes required USDC and checks total collateral availability.
- Uses
_planExternalVaultWithdrawal(requiredUsdc)to compute deficit vstotalUsdcHeld. - Commit phase withdraws deficit through
_withdrawUsdcFromExternalVaultswhen needed.
Withdrawal source order:
- First:
redemptionPriorityVaultIds(if configured). - Fallback: single-item array with
defaultStakingVaultId. - If neither exists and held balance is insufficient, redemption reverts (
InsufficientBalance).
Liquidation-mode redemption uses the same external-withdraw planning pattern.
Hedger Flow
Hedger opens / adds margin
HedgerPooltransfers USDC intoQuantillonVault.vault.addHedgerDeposit(...)increasestotalUsdcHeld.
Hedger closes / removes margin / liquidation payout
HedgerPoolcallsvault.withdrawHedgerDeposit(...).- Vault uses held USDC first; if needed, it withdraws from external vaults using the same priority logic as redemptions.
Governance and Operator Controls
QuantillonVault controls:
setStakingVault(vaultId, adapter, active)(GOVERNANCE_ROLE)setDefaultStakingVaultId(vaultId)(GOVERNANCE_ROLE)setRedemptionPriority(vaultIds[])(GOVERNANCE_ROLE)harvestAndDistributeVaultYield(vaultId)(YIELD_DISTRIBUTOR_ROLE) — harvest + 3-way split to stakers/hedger/treasurycreditVaultYield(vaultId, usdcAmount)(YIELD_DISTRIBUTOR_ROLE) — credit USDC into stQEURO as QEURO backingsetHedgerStakingYieldHaircutBps(bps)/setHedgerYieldRecipient(addr)(GOVERNANCE_ROLE)deployUsdcToVault(vaultId, usdcAmount)(VAULT_OPERATOR_ROLE)
Factory binding:
selfRegisterStQEURO(factory, vaultId, vaultName)links vault id to stQ token (GOVERNANCE_ROLE).
Automatic vs Operational Actions
Automatic:
- Mint routing to default/explicit vault (if configured).
- Redemption and hedger withdrawals sourcing liquidity from external vaults when needed.
Operational:
- Adapter configuration and activation.
- Default vault and redemption-priority policy.
- Deploying idle held USDC (
deployUsdcToVault). - Harvesting + distributing adapter yield (
harvestAndDistributeVaultYield).
Key Events for Indexer and Admin Read Models
VaultRegistered(factory)StakingVaultConfiguredDefaultStakingVaultUpdatedRedemptionPriorityUpdatedUsdcDeployedToExternalVaultUsdcWithdrawnFromExternalVaultVaultYieldDistributed(harvest + 3-way split)
Practical Ops Notes
- If
vaultIdconfig is missing/inactive, vault-aware actions revert (InvalidVault/ config errors). - If held + external principal cannot satisfy required payouts, flows revert (
InsufficientBalance). - Correct default and priority setup is critical to predictable redemption behavior.
Source Files
src/core/QuantillonVault.solsrc/core/HedgerPool.solsrc/core/stQEUROFactory.sol