Skip to main content

Process

Deposit in two onchain steps:
  1. Call approve(vaultAddress, amount) on the ERC-20 token contract.
  2. Call deposit(user, tokenAddress, amount) on the chain’s deposit vault contract.
Vault addresses are served by GET /registry/vaults. The deposit() call pulls tokens from msg.sender, so the approval must be from the same wallet that sends the deposit transaction. The vault checks canDeposit(msg.sender), rejects zero-amount deposits, and transfers with safeTransferFrom(tokenAddress, msg.sender, address(this), amount). Approving the exact deposit amount limits the ERC-20 allowance to that deposit. Unlimited approval lets later deposit() calls from the same wallet reuse allowance, but leaves a broader token allowance in place until the wallet reduces or revokes it. The vault also reads decimals() from the token and rejects amounts that would overflow normalization to Tplus 18-decimal internal units or round down to zero. On the first deposit for a user, the amount must meet the token’s configured minFirstDepositAmounts value. First-time depositors can use the overloaded deposit variant that emits an initial multisig signer configuration; the clearing engine applies it during deposit ingestion after verifying the master-config signature. Blockchain clients ingest the vault’s Deposited event, verified across multiple independent RPC providers with majority agreement, and credit the balance after the chain’s confirmation policy is met. Deposit nonces are tracked per user per chain; each deposit is credited exactly once. A canonical-block check runs after confirmations; events on orphaned blocks are dropped and re-ingested from the canonical chain. Funds remain in the vault contract while crediting is pending.

Chains and confirmation times

Production asset-config rows currently use this EVM chain set. Supported tokens vary by chain; use GET /registry/assets for per-asset availability. Deposits and withdrawals are ingested only after a per-chain confirmation policy is met - a number of block confirmations, or the chain’s own finality - followed by the canonical-block check above. Settlements are exempt: they ingest immediately, with re-org safety coming from the settlement lock and nonce instead (see Settlement). These are source-defined default policies. The live vault addresses are served by GET /registry/vaults; the onchain Credential Manager stores each registered vault’s ChainConfig, which can override the confirmation counts. Do not hardcode policies when operating from live registry state.

Decimals

Balances are normalized internally to 18 decimals (per-token decimals: POST /registry/decimals).

Rebalancing fees and rebates

A deposit can earn a rebate or pay a fee of up to 2.5%, depending on how it shifts the chain’s vault relative to its target weight: a deposit into an underweight vault earns a rebate, into an overweight vault pays a fee. It is applied when the balance is credited, and rebates are paid from the protocol fee account. See Rebalancing.

Deposit caps

Each (asset, chain) pair has two caps, published in asset parameters: a total deposit cap (maxDeposits) and a rolling 1-hour cap (max1hrDeposits). A deposit that breaches either is still credited, but as an isolated Address(token@chain) balance - not fungible with the pooled asset and not usable for leverage until caps allow. See Asset fungibility.

Fungibility

The same token across chains maps to one Tplus asset. See Asset fungibility.