DepositLimitRegistry
contract — the platform sets each wallet’s tier and caps from its KYC
level, and vault.depositERC20(...) consults the registry on every
call. A wallet whose tier has not been set yet cannot deposit at all
(KycRequired()).
Caps by KYC level
The platform writes the same figure to the per-deposit and 30-day
caps, so in practice the 12-month total is the one that binds, and a
single deposit can use the whole remaining 12-month allowance.
The effective cap can be lower than the table: a deposit limit the user
sets for responsible gambling, or a compliance override, tightens it,
and testnet wallets can carry different figures. Always read the live
values from
GET /api/me/deposit-limits
rather than hard-coding the table.
Caps only rise when the wallet clears a higher KYC level — there is
no API to raise them. Partner-specific arrangements are agreed at
onboarding — contact your integration manager.
Partner-backed sub-accounts
Sub-accounts under amulti_wallet partner with
requirePerWalletKyc=false (see Partner kinds)
are provisioned at the VIP tier with no per-wallet custom cap the
moment the first request for the sub-account hits the API, so no
on-chain deposit ceiling applies. Deposit / trade / withdraw
restrictions are cleared in the same auto-onboarding step. No admin
call required after the partner key is issued — the five on-chain ops
(setTier(VIP), setCustomCaps(0, 0, 0), setDepositsRestricted(false),
setTradingRestricted(false), setWithdrawalsRestricted(false)) are
enqueued automatically and confirmed on-chain within ~30 sec.
setCustomCaps(0, 0, 0) clears any per-wallet override, so the VIP
tier’s defaults apply.
The partner has taken KYB-level responsibility for its sub-accounts at
the partner record. Need a per-sub-account deposit cap? Contact your
integration manager.
Rolling-window semantics
Caps are enforced over rolling windows, not calendar months:- Per deposit: a single deposit must stay ≤ the per-deposit cap.
- 30-day: deposits recorded in the current UTC day and the previous 29 days (1-day buckets), plus this deposit, must stay ≤ the 30-day cap.
- 12-month: deposits recorded in the current 30-day bucket and the previous 11 (360 days in total), plus this deposit, must stay ≤ the 12-month cap.
Reading your current usage
tier is the wallet’s on-chain registry tier — 0 = not set yet,
1–3 = capped tiers, 4 = VIP, 5 = rejected. It is not the KYC
level itself: Basic and Standard both read 1
(Enhanced reads 2, Advanced 3), so tell levels apart by caps, not
by tier. While tier is 0, vault.depositERC20 reverts with
KycRequired() — see Initialisation timing
below.
A cap of "79228162514264337593543.950335" (type(uint96).max) is
the on-chain “no cap” sentinel, not a real limit — treat that window
and its remaining as unlimited. A VIP wallet with no tighter limit
reads it for every cap.
used sums the deposits still inside each rolling window at read
time, so a deposit stops counting the moment its bucket rolls out —
there is no window-reset timestamp to wait for. remaining is
cap − used, floored at 0. After a deposit mines, used and
remaining can lag the chain by up to a minute.
restrictions.depositBlocked is true whenever a deposit would be
refused right now: tier not set, a rejected wallet, a deposit
restriction, or a cap already fully used — check remaining before
attributing it to compliance. tradeBlocked and withdrawBlocked
report the same for trading and withdrawals (a Basic wallet can
deposit but not withdraw).
Initialisation timing
The platform writes a wallet’s tier and caps toDepositLimitRegistry
in its own back-office transactions, driven by the wallet’s KYC level
(for partner-backed sub-accounts, the
VIP tier on the first request). This runs independently of vault
deploy: GET /api/me/vault returning deployed: true does not mean
the wallet can deposit yet. Until the tier lands, vault.depositERC20
reverts with KycRequired() (selector 0x709ea86e).
Before the first deposit, poll GET /api/me/deposit-limits until
tier is non-zero and restrictions.depositBlocked is false.
Stop polling at tier: 5: the wallet was rejected by compliance and
deposits revert with UserIsRejected(). If tier is 1–4 but
depositBlocked stays true, the cause is a deposit restriction or
a used-up cap, not timing.
Exceeding the cap
When a deposit reverts withSingleDepositCapExceeded(),
Window30dCapExceeded() or Window12mCapExceeded(), the on-chain
transaction does not settle and no USDC moves — the sender simply pays
gas for the revert. Recovery options:
- Deposit a smaller amount. Stay ≤ the smallest of
caps.singleDeposit,remaining.thirtyDayandremaining.twelveMonthfromGET /api/me/deposit-limits. Right after a deposit mines,remainingcan still show the pre-deposit figure for up to a minute, so allow for any deposit you made in the last minute. - Wait for older deposits to roll out.
useddrops as buckets leave the window (see Rolling-window semantics); re-readGET /api/me/deposit-limits. - Move to a higher KYC level. The cap follows the wallet’s KYC level; for partner-specific arrangements contact your integration manager.
Withdrawals are not symmetric
Cap accounting is deposit-only — withdrawing USDC from the vault does not “free up” deposit cap retroactively. The window is a sliding view of inflow, not a net-flow accounting. This matches the regulatory intent (AML deposit ceilings) and the on-chainDepositLimitRegistry
implementation.
Next
Deposits overview
Approve + depositERC20 lifecycle.
Backend auto-deploy
How the platform deploys your vault; deposit limits are set separately.