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) |
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 three ABI snippets. Copy these into your project as a JSON file or inline constant.DistributorCodeDepositor ABI
ERC-20 ABI (for approvals and allowance checks)
Accountant ABI (for slippage calculation)
Contract Method Reference
deposit(depositAsset, depositAmount, minimumMint, to, distributorCode)
| 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. |
depositWithPermit(depositAsset, depositAmount, minimumMint, to, distributorCode, deadline, v, r, s)
Same parameters as deposit(), plus:
| 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
rate represents the amount of the deposit asset per 1e18 vault shares (i.e., per one full share).
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) / rate) × (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) |
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.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.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