Earn (ERC-4626 Vaults)
Earn lets a user put a shielded balance to work in an ERC-4626 yield vault and pull it back out — without the funds ever leaving the shielded pool. A deposit spends a private asset note, routes it through the vault via the external call gateway, and credits the vault shares back as a new private note; a withdraw redeems those share notes the same way. The vault call itself is public on-chain, but the account that owns the deposited note is not.Earn is a v2 feature enabled per deployment. The server advertises
externalGatewayAddress in /info when the
gateway is enabled. Use sdk.vault.getGatewayConfig() and each operation’s
availability to detect support before offering it.EARN_VAULT_MODE controls the optional vault metadata catalog, not Gateway
execution. A deployment can leave it disabled and still support
earnDeposit() and earnRedeem() for ERC-4626 routes advertised by
getRegisteredTokens().How it works
An earn deposit is a gateway unshield. Instead of paying a private note out to a public address, the SDK signs an authorization that lets the gateway run the vault call and credit the result straight back into the pool:- Preview & authorize. The SDK reads the vault on-chain (
asset(),previewDeposit/previewRedeem), derives aminOutputAmountfloor from your slippage bound, and signs thePB:WITHDRAW:GATEWAY:v2authorization for exactly that request. - Execute. The pool spends the input note under the epoch proof, and the gateway calls the vault. The output is measured on-chain, not trusted from the preview.
- Credit. The measured vault output creates a pending gateway deposit. A later deposit proof credits it as a new private note. The owner’s identifying keys never appear in the transaction.
- Refund on failure. If the vault reverts, the request expires, or the fill
would land below the signed
minOutputAmount, the input is recorded as a fallback deposit and credited as a private note by a later deposit proof. Funds never leave the pool uncredited.
SDK API shape
The earn surface lives on the vault resource (sdk.vault). Gateway and
token capability discovery are public. When configured, catalog and history
reads are public too. The two write operations require an authenticated
session. Settlement is tracked with sdk.transactions.getUnshieldStatus,
which also requires a session.
earnDeposit / earnRedeem take an EarnParams. amount is net — exactly
what enters the vault call (assets for a deposit, shares for a redeem); the
Gateway fee replaces the regular unshield fee and is charged on top, so your
notes must cover amount + fee.
maxSlippageBps bounds the fill below the on-chain preview (default 100 =
1%).
maxDeposit() using
gateway.executorAddress as the receiver. A policy-approved route may still
have no live capacity; disable deposits when maxDeposit() is below the
requested asset amount. The SDK separately validates asset() and reads
previewDeposit() or previewRedeem() while building the signed request.
Tracking settlement
An earn operation returns anEarnResult with a requestId. Poll the unshield
status and read the gateway projection, since credit lands in a later epoch.
gateway.creditStatus === 'completed' means the private note was credited.
gateway.creditStatus === 'rescued' is a terminal recovery outcome: the escrow
was paid to the rescue destination, so stop waiting for private credit.
The top-level completed flag only confirms the original unshield epoch.
Vault history charts
This section applies only when the deployment enables the optional Earn catalog service. WithEARN_VAULT_MODE=disabled, catalog and history endpoints
are not mounted and return 404; this does not disable Gateway execution.
getEarnVaultHistory and getEarnVaultCharts return cached TVL and net-APY
series suitable for rendering a chart. Both are public — usable before
login.
metricis'tvlUsd'or'netApy';periodis'1w' | '1m' | '3m' | 'all'(server default1w).getEarnVaultChartsfetches both metrics at once and rejects if either fails — callgetEarnVaultHistorytwice if you want partial results.- APY values are decimal ratios (
0.05= 5%); TVL values are USD. Points ascend by timestamp. - A
nullpoints[].valueis an upstream gap — render it as a gap rather than interpolate across it. - Check
metadata.statebefore presenting the data as current. Today it is one offresh,stale(upstream unavailable — this is the last good series),synthetic(deterministic testnet data), orunsupported. It is an open set: treat an unrecognized state as renderable data of unknown freshness, not an error. - While the server’s cache warms, a cold request may answer
503with a retry-after hint; the SDK’s standard retry policy already honors it.
Trust and privacy
Earn is a deposit-and-credit extension: the gateway can only spend the note you authorize and credit the measured result back into the pool. It grants no new authority to move or seize funds.
A gateway-origin note joins the same shared note tree as every other deposit
and transfer, so its anonymity set is the full mixed pool. Earn hides who
deposited into the vault, not that the vault was used — the vault call
(target and amount) is public on-chain. The
minOutputAmount floor is signed,
so no operator can settle a deposit into a worse-than-authorized fill; the worst
case is a refund of the input. An unprocessed gateway deposit can be rescued
after the cancel delay using its designated rescue authority.
Launch limitations
These are constraints of the current implementation:- Enabled per deployment. A deployment without a gateway has no
externalGatewayAddressin/info, andgetGatewayConfig()returnsenabled: false. Always feature-gate onenabledand the operation’savailability.canSubmitvalue. - Operator-approved routes. Only ERC-4626 calls allowed by the effective
Gateway policy and backed by registered pool tokens are usable. Discover
those routes from
getRegisteredTokens()capabilities. If the optional catalog is enabled, also honor the availability and warnings returned bylistEarnVaults(). - Slippage is a floor, not a guarantee of execution. A fill below the signed
minOutputAmountrefunds the input via the fallback receipt instead of executing; surface that outcome rather than treating the request as failed. - History is a best-effort cached read. Freshness is reported by
metadata.state, and a cold cache can briefly503. Do not treat astaleor unknown state as an error. - Single-chain. Earn works on a chain that hosts both a pool and a deployed gateway.
Using it from the SDK
- TypeScript — the earn methods on
sdk.vault. See the TypeScript API reference. - WASM — the same methods exposed top-level on
sdk(sdk.earnDeposit,sdk.earnRedeem,sdk.getGatewayConfig). See the WASM API reference. - CLI — the
earnsubcommands. See the Commands reference. - iOS / Android / React Native —
earnDeposit/earnRedeemplus typed catalog and history reads (listEarnVaults,getEarnVault,getGatewayConfig,getEarnVaultHistory,getEarnVaultCharts). The*Jsonvariants of the reads remain for callers that parse the wire shape themselves. See the platform API references.