Non-custodial design
What “non-custodial” means in Aqua0's vault model, and what it does not mean.
This page describes the vault architecture (per-asset ERC-4626 vaults with ERC-7540 async redemption) that mainnet-beta ships on. It supersedes the previous description of the Shared Liquidity Pool (SLP) model.
What it means
Deposits sit in a per-asset, per-chain ERC-4626 vault (e.g. Base aqUSDC, a separate contract
and separate share price from Unichain aqUSDC). Depositing mints yield-bearing vault shares; the
share price moves as the vault earns (or loses), so you don't need a separate reward token or
manual claim step to capture yield. The vault, not a team-controlled wallet, holds the funds, and
the team cannot move deposited assets to an arbitrary address through ordinary contract calls.
Capital in the vault is either:
- idle — sitting in the vault as plain ERC-20 balance, or
- deployed — put to work by a registered adapter (e.g. providing JIT liquidity, executing a cross-chain strategy) so it isn't just parked doing nothing.
totalAssets() (and so the share price) is the sum of both.
Withdrawing: sync vs async
- Free balance (idle capital): a standard synchronous ERC-4626
redeem— instant, no request/wait step. - Deployed capital: ERC-7540 asynchronous redemption —
requestRedeem→ the protocol frees the capital (adapter unwind / settlement) →claim. This is the flow used when your shares represent capital currently working at a venue rather than sitting idle.
See Async redeem semantics for the full request/claim lifecycle if you're integrating against it.
The never-trapped guarantee
An async redemption request becomes claimable when either:
- the capital is attested free (the protocol's signer confirms the underlying position has been unwound/settled), or
- a per-route timeout backstop elapses —
now >= requestTime + timeout[route].
Every per-route timeout is itself bounded by an immutable, compile-time constant,
GLOBAL_MAX_TIMEOUT = 7 days — no owner, governance, or upgrade can raise a route's timeout past
that ceiling. This is what makes redemption never-trapped: even in a worst case where the
attestation path fails entirely, every request becomes claimable on its own within at most 7 days,
with no discretionary step required. Beta's deployed defaults are tighter than the ceiling
(same-chain 1 hour, cross-chain 12 hours) and may be tuned down further as real settlement
latency is measured, but can never be tuned up past the 7-day immutable maximum.
What non-custodial does not mean
It does not eliminate:
- smart contract risk (the vault, adapters, and Composer are new contracts under audit — see Audits & security process)
- chain risk
- bridge/messaging risk in cross-chain flows
- off-chain trust in specific, narrowly-scoped signing keys (see below) — Aqua0 is non-custodial in that the team cannot arbitrarily redirect funds, but it is not fully trustless: a small number of bounded, monitored roles have real (though limited) power.
Privileged roles and what each can and cannot do
Vault access control is role-based (OpenZeppelin AccessControlUpgradeable), each role a distinct
key held by a distinct signer:
| Role | Can do | Cannot do |
|---|---|---|
PNL_REPORTER_ROLE | Report the cross-chain in-flight PnL delta once per epoch, rate-clamped (see below) | Move funds, mint shares directly, exceed the per-epoch clamp, or report a loss "away" — losses are recognized from events, not from what the reporter says |
COMPOSER_ROLE | Route deployed capital through registered adapters only | Pull funds to an arbitrary address, or use an unregistered adapter |
GUARDIAN_ROLE | Veto/pause (circuit breaker) | Unpause alone — resuming requires the timelock'd multisig, not the guardian |
PAUSER_ROLE | Pause vault operations | Upgrade contracts or change roles |
UPGRADER_ROLE (held by a timelock'd multisig) | Upgrade the vault implementation or singleton contracts | Execute instantly — every upgrade passes through a timelock delay, giving the team and the community a response window before it takes effect |
REGISTRAR_ROLE / OPERATOR_ROLE / RECORDER_ROLE | Register adapters / operate strategy lifecycle / record settlement bookkeeping, each within its own narrow surface | Bypass the roles above |
The hybrid PnL model — the one place off-chain trust remains
Vault share price is not fully self-attested. It's a hybrid:
- Same-chain realized PnL is settlement-derived and trustless. When an adapter settles a position, the resulting gain or loss is applied from the settlement event itself — no key can move this number; it's a direct on-chain fact.
- Cross-chain in-flight PnL (capital currently deployed on another chain, before the bridge/
message finalizes) can't be observed on-chain in real time, so it's filled by a bounded
PNL_REPORTER_ROLE. This is the one place a signed, off-chain-attested number feeds into the share price, and it is deliberately constrained on every axis:- Isolated, KMS-custodied key — a dedicated signer, not shared with any other role, held in a managed KMS (not an operator's laptop or a plaintext env var).
- Per-epoch rate clamp — a single report can move the share price by at most 25 bps/day
at beta's deployed setting, and that ceiling is itself capped by an immutable
MAX_BPS_PER_EPOCH_CEILING = 500 bpsthat no owner action can raise. The clamp bounds the rate of change, not a lifetime total — a compromised reporter cannot instantly move the share price, but it could still push a small amount every epoch until caught, which is why ongoing off-chain monitoring and alerting on this role is a load-bearing part of this design, not a formality. - Losses are recognized immediately and are events-authoritative — the reporter can only make the reported number worse for itself, never better; a malicious or compromised reporter cannot hide or delay a real loss.
- Gains are streamed/vested over the epoch, not applied atomically, removing the incentive to sandwich a single large positive report.
- Reconciliation and clawback — when the underlying bridge/settlement actually lands, the protocol reconciles the reporter's prior delta against the real, adapter-emitted settlement amount. If the reporter over-reported, the excess is clawed back from any gains that hadn't fully vested yet.
In plain terms: a compromised PNL_REPORTER_ROLE key can nudge the share price up by a bounded,
small amount per epoch, and any over-statement is caught and clawed back at reconciliation — it
cannot drain the vault, cannot move funds, and cannot hide a real loss. It is a materially
narrower trust assumption than a role that can authorize withdrawals, and it exists only to cover
the in-flight cross-chain gap that same-chain settlement can't observe on its own.
PNL_REPORTER_ROLE, COMPOSER_ROLE, and UPGRADER_ROLE are this design's central off-chain trust
assumptions. They are bounded and monitored (rate clamp, registered-adapter allowlist, and timelock
delay respectively) specifically so that a single key compromise cannot immediately drain funds —
but compromise of any of them is still a serious incident. See
Risks & disclosures for the full breakdown.
Open items not yet finalized
Aqua0's V4 JIT liquidity design and its relationship to the vault (whether/how V4 JIT capital is backed by vault deposits) is an open decision under review and is intentionally not described here. Nothing on this page should be read as a claim about JIT capital efficiency or how many pools a single deposit can back — that framing predates the vault model and is being re-evaluated for beta.