How Deposits Work
When you deposit tokens (e.g., USDC) into a vault, you receive vault shares in return. These shares represent your proportional ownership of the vault’s assets and appreciate in value as the vault earns yield. There are two ways to deposit:| Flow | Transactions | Best For |
|---|---|---|
| Standard (Approve + Deposit) | 2 transactions | All tokens, all wallets |
| Permit (Sign + Deposit) | 1 transaction | Supported tokens only (USDC, USDG, pyUSD, USD₮0) |
KYT Vaults
TheAttestation struct is passed as the last parameter before any permit fields:
What You’ll Need
| Requirement | Description |
|---|---|
| Contract addresses | distributorCodeDepositorAddress and accountantAddress — see Vault Discovery |
| ABI | Provided below — just copy into your project |
| RPC endpoint | An Ethereum node URL (Alchemy, Infura, QuickNode, etc.) |
| Private key or wallet | To sign and send transactions |
| Deposit tokens | The token you’re depositing (e.g., USDC) + ETH for gas |
ABI Reference
You need the DistributorCodeDepositor ABI, the ERC-20 ABI, and the Accountant ABI. Copy these into your project as a JSON file or inline constant.DistributorCodeDepositor ABI
Bothdeposit() and depositWithPermit() include the _attestation tuple parameter for KYT compliance.
ERC-20 ABI (for approvals and allowance checks)
Accountant ABI (for slippage calculation)
Contract Method Reference
deposit
deposit(depositAsset, depositAmount, minimumMint, to, distributorCode, _attestation)
| Parameter | Type | Description |
|---|---|---|
depositAsset | address | The ERC-20 token address to deposit (e.g., USDC: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) |
depositAmount | uint256 | Amount in the token’s smallest unit. USDC has 6 decimals, so 1000000 = 1 USDC. |
minimumMint | uint256 | Minimum shares to receive — protects against slippage. Set to 0 to accept any amount. |
to | address | Address that receives the minted vault shares (usually the depositor) |
distributorCode | bytes | Tracking code for referrals/attribution. Pass 0x (empty bytes) if not applicable. |
_attestation | tuple | Compliance attestation struct. Pass empty/zero values for now — see note above. |
| Field | Type | Description | Default Value |
|---|---|---|---|
uuid | string | Unique attestation identifier | "" (empty string) |
expiration | uint256 | Unix timestamp when the attestation expires | 0 |
attester | address | Address of the attestation provider | 0x0000000000000000000000000000000000000000 |
signature | bytes | Cryptographic signature from the attester | 0x (empty bytes) |
depositWithPermit
depositWithPermit(depositAsset, depositAmount, minimumMint, to, distributorCode, _attestation, deadline, v, r, s)
Same parameters as deposit() (including the _attestation tuple), plus the permit fields appended after the attestation:
| Parameter | Type | Description |
|---|---|---|
deadline | uint256 | Unix timestamp after which the permit expires |
v | uint8 | Recovery byte of the EIP-2612 permit signature |
r | bytes32 | First 32 bytes of the permit signature |
s | bytes32 | Second 32 bytes of the permit signature |
Distributor Codes
ThedistributorCode parameter is used for referral attribution. If Paxos Labs has provided you with a distributor code, encode it as bytes (e.g., toHex('your_code') in JavaScript, b'your_code' in Python, []byte("your_code") in Go).
If you don’t have one, pass empty bytes (0x, b"", []byte{}).
Calculating minimumMint (Slippage Protection)
The vault’s Accountant contract publishes the exchange rate between the deposit token and vault shares. Use it to calculate a safe minimumMint.
Contract call
rateInQuote represents the amount of the deposit asset per 1e18 vault shares (i.e., per one full share). Pass the deposit token address as the quote parameter.
Calculation
SLIPPAGE_BPS is your slippage tolerance in basis points (e.g., 50 = 0.5%).
Setting
minimumMint to 0 disables slippage protection entirely. This is
fine for testing but not recommended for production — a front-running bot
could manipulate the rate between your transaction submission and execution.Standard Deposit Walkthrough
The standard flow requires two transactions: an ERC-20 approval followed by the deposit.Check existing allowance (read)
Call the deposit token’s If the returned value is ≥ your
allowance() to see if the DistributorCodeDepositor already has sufficient spending permission.depositAmount, skip to Step 3.Approve the DistributorCodeDepositor (transaction)
Call Wait for the transaction to be mined before proceeding.
approve() on the deposit token, granting the DistributorCodeDepositor permission to transfer your tokens.Calculate minimumMint (read)
Query the exchange rate and compute slippage protection.Then calculate:
minimumMint = ((depositAmount × 1e18) / rateInQuote) × (10000 − SLIPPAGE_BPS) / 10000Execute the deposit (transaction)
Call The return value is the number of vault shares minted.
deposit() on the DistributorCodeDepositor.Example values (1,000 USDC deposit on Ethereum mainnet)
| Parameter | Value |
|---|---|
depositAsset | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
depositAmount | 1000000000 (1,000 × 10^6) |
minimumMint | Calculated from Accountant rate |
to | Your wallet address |
distributorCode | 0x (empty) |
_attestation | { uuid: "", expiration: 0, attester: "0x0000000000000000000000000000000000000000", signature: "0x" } |
Permit Deposit Walkthrough
For tokens that support EIP-2612 permits, you can combine approval and deposit into a single transaction.| Token | Permit Support |
|---|---|
| USDC | Yes |
| USDG | Yes |
| pyUSD | Yes |
| USD₮0 | Yes |
| USDT | No — use standard approve + deposit |
Sign the EIP-712 permit message (off-chain)
Construct and sign an EIP-712 typed data message. This is an off-chain signature — no gas required.EIP-712 Domain (varies by token — this example is for USDC on Ethereum):
Permit message:
The EIP-712 type structure:Sign using your wallet’s
| Field | Value |
|---|---|
name | "USD Coin" |
version | "2" |
chainId | 1 |
verifyingContract | USDC token address |
| Field | Value |
|---|---|
owner | Your wallet address |
spender | distributorCodeDepositorAddress |
value | depositAmount |
nonce | From Step 1 |
deadline | Unix timestamp (e.g., now + 1 hour) |
signTypedData (or equivalent EIP-712 signing method). Parse the resulting signature into v, r, s components.Execute depositWithPermit (transaction)
Call The contract verifies the permit signature on-chain, transfers your tokens, and mints vault shares — all in a single transaction.
depositWithPermit() on the DistributorCodeDepositor with the permit signature. Note the _attestation tuple is placed before the permit parameters.Troubleshooting
Transaction reverts with no error message
Transaction reverts with no error message
The most common cause is that
minimumMint is set too high relative to the
current exchange rate. Set it to 0 for testing or recalculate from the
Accountant’s getRateInQuoteSafe().PermitFailedAndAllowanceTooLow
PermitFailedAndAllowanceTooLow
The permit signature is invalid and there’s no existing ERC-20 approval.
Double-check the permit domain parameters (
name, version,
verifyingContract) match the token’s EIP-712 domain. Or switch to the
standard approve + deposit flow.ERC20: insufficient allowance
ERC20: insufficient allowance
You haven’t approved the DistributorCodeDepositor to spend your tokens. Call
approve() on the token contract before calling deposit().ERC20: transfer amount exceeds balance
ERC20: transfer amount exceeds balance
Your wallet doesn’t hold enough of the deposit token. Check your balance
before depositing.
USDT approval fails
USDT approval fails
USDT requires resetting the allowance to
0 before setting a new value if
there’s an existing non-zero allowance. Call approve(spender, 0) first,
then approve(spender, amount). Other tokens (USDC, USDG, pyUSD) allow
overwriting an existing approval directly.Transaction reverts without attestation parameter
Transaction reverts without attestation parameter
The
DistributorCodeDepositorV1 contract requires the _attestation tuple
parameter. If you omit it or use an older ABI without the attestation field,
the transaction will revert. Ensure you’re using the ABI from this guide and
passing the attestation struct (empty values are fine for now). Contact the
Paxos Labs team to implement your compliance
policy.Next Steps
- Direct Withdrawals — Submit a withdrawal order
- Direct Cancellations — Cancel a pending withdrawal
- Vault Queries & Monitoring — Read APY, TVL, check balances, and monitor withdrawal status
- SDK Deposits Guide — Use the Amplify SDK instead