EVM Actions
Deposit, request withdrawals, claim redemptions, and manage token approvals on EVM vaults with the Upshift SDK.
Overview
EVM write operations require a connected wallet with a signer. The SDK supports all vault versions (evm-0, evm-1, evm-2) and automatically selects the correct contract ABI and function signatures.
Setup
import { ethers } from 'ethers';
import AugustSDK from '@augustdigital/sdk';
// Initialize SDK
const sdk = new AugustSDK({
appName: '<APP_NAME>', // required
providers: {
1: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
},
});
// Connect wallet and set signer
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
sdk.evm.setSigner(signer);
const userAddress = await signer.getAddress();Vault Deposit
Deposit tokens into a vault. The SDK automatically handles different vault versions (evm-0, evm-1, evm-2) and adapter deposits.
sdk.evm.vaultDeposit({
target: string;
wallet: string;
amount: string | bigint | number;
wait?: boolean;
depositAsset?: string; // Optional: for adapter deposits
chainId?: number; // Optional: for adapter routing
poolName?: string; // Optional: for adapter routing
}): Promise<string>Vault Version Detection
The SDK automatically detects the vault version and uses the correct deposit method:
| Version | Deposit Function | Parameters | Use Case |
|---|---|---|---|
evm-0 | deposit(uint256, address) | 2 params | Legacy vaults |
evm-1 | deposit(uint256, address) | 2 params | Standard vaults |
evm-2 | deposit(address, uint256, address) | 3 params | Multi-asset vaults |
| Adapter | Various | Depends on adapter type | Alternative token deposits |
You don't need to specify the version - the SDK detects it automatically from the vault's version field.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
target | string | Yes | Vault contract address |
wallet | string | Yes | User wallet address |
amount | string | bigint | number | Yes | Amount to deposit |
wait | boolean | No | Wait for confirmation (default: false) |
depositAsset | string | No | Token to deposit (defaults to underlying) |
chainId | number | No | Chain ID for adapter routing |
poolName | string | No | Pool name for adapter routing |
Returns
Transaction hash as string
Example: Standard Deposit
// Deposit underlying token
const txHash = await sdk.evm.vaultDeposit({
target: '0x80E1048eDE66ec4c364b4F22C8768fc657FF6A42',
wallet: userAddress,
amount: '100', // 100 tokens
wait: true,
});
console.log('Deposit successful:', txHash);How It Works for Each Version
EVM-0 & EVM-1 Vaults (Standard)
Contract Function: deposit(uint256 assets, address receiver)
Behavior:
- Deposits the vault's underlying token only
- 2 parameters: amount and receiver
- Automatic approval of underlying token to vault
Example:
// Upshift USDC (evm-1)
await sdk.evm.vaultDeposit({
target: '0x80E1048eDE66ec4c364b4F22C8768fc657FF6A42',
wallet: userAddress,
amount: '100', // 100 USDC
wait: true,
});
// SDK calls: vault.deposit(100e6, userAddress)EVM-2 Vaults (Multi-Asset)
Contract Function: deposit(address assetIn, uint256 amount, address receiver)
Behavior:
- Accepts multiple whitelisted tokens (listed in
vault.depositAssets) - 3 parameters: asset address, amount, and receiver
- Automatic approval of selected token to vault
Example:
// Get vault to see deposit options
const vault = await sdk.getVault({
vault: '0x18EE038C114a07f4B08b420fb1E4149a4F357249',
chainId: 1,
});
console.log(
'Can deposit:',
vault.depositAssets.map((a) => a.symbol),
);
// Output: ["USDC", "USDT", "DAI"]
// Deposit any whitelisted asset
await sdk.evm.vaultDeposit({
target: vault.address,
wallet: userAddress,
amount: '100',
depositAsset: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
chainId: 1,
wait: true,
});
// SDK calls: vault.deposit(USDT_ADDRESS, 100e6, userAddress)Note: For EVM-2 vaults, you can optionally specify depositAsset. If omitted, SDK uses the first asset in depositAssets array (usually the primary/underlying token).
Adapter Vaults (Alternative Tokens)
Contract Functions: Various depending on adapter type
Behavior:
- Enables deposits with tokens beyond the vault's standard accepted tokens
- Uses wrapper contracts or swap protocols
- Requires
depositAsset,chainId, and sometimespoolNameparameters
Adapter Types:
- Native Token Adapter (e.g., ETH → wstETH)
- Wraps native tokens before depositing
- Uses
WrapperAdaptercontract - Example: Treehouse Growth
- Token Wrapper Adapter (e.g., WETH → wstETH)
- Wraps ERC20 tokens before depositing
- Uses
WrapperAdaptercontract - Example: Treehouse Growth
- Swap Adapter (e.g., USDC → WBTC)
- Swaps tokens via Paraswap before depositing
- Uses
PoolAdaptercontract - Example: BTC Multi-Token
Example: Native ETH Deposit
// Treehouse Growth accepts: wstETH, WETH, ETH (via adapter)
await sdk.evm.vaultDeposit({
target: '0x5Fde59415625401278c4d41C6beFCe3790eb357f',
wallet: userAddress,
amount: '1.0', // 1 ETH
depositAsset: '0x0000000000000000000000000000000000000000', // Native ETH
chainId: 1,
poolName: 'Treehouse Growth',
wait: true,
});
// SDK calls: wrapperAdapter.depositETH() with valueExample: WETH Deposit (via adapter)
await sdk.evm.vaultDeposit({
target: '0x5Fde59415625401278c4d41C6beFCe3790eb357f',
wallet: userAddress,
amount: '1.0',
depositAsset: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
chainId: 1,
poolName: 'Treehouse Growth',
wait: true,
});
// SDK calls: wrapperAdapter.deposit() after approving WETHExample: Swap Adapter Deposit
// BTC Multi-Token accepts WBTC but can swap from USDC
await sdk.evm.vaultDeposit({
target: '0xBTCVaultAddress...',
wallet: userAddress,
amount: '10000', // 10,000 USDC
depositAsset: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
chainId: 1,
poolName: 'BTC Multi-Token',
wait: true,
});
// SDK:
// 1. Gets Paraswap quote (USDC → WBTC)
// 2. Approves USDC to PoolAdapter
// 3. Calls: poolAdapter.swapAndDeposit()Automatic Detection Flow
// Step 1: Get vault info
const vault = await sdk.getVault({ vault: vaultAddress, chainId: 1 });
// Step 2: SDK checks vault.version
if (vault.version === 'evm-2') {
// Use 3-param deposit(address, uint256, address)
} else if (depositAsset && depositAsset !== vault.underlying.address) {
// Use adapter logic
} else {
// Use 2-param deposit(uint256, address)
}
// Step 3: SDK handles approvals automatically
// Step 4: SDK calls correct contract methodWhen to Use Each Parameter
| Parameter | Required | Use When |
|---|---|---|
target | Always | Vault address |
wallet | Always | User's address |
amount | Always | Deposit amount |
wait | Optional | Want to wait for confirmation |
depositAsset | Sometimes | Using adapter OR EVM-2 with non-primary token |
chainId | Sometimes | Using adapter |
poolName | Sometimes | Using adapter (helps with routing) |
Quick Reference: Vault Versions
How to check which version a vault uses:
const vault = await sdk.getVault({ vault: vaultAddress, chainId: 1 });
console.log('Version:', vault.version); // "evm-0", "evm-1", or "evm-2"
console.log('Has adapters:', vault.depositAssets.length > 1);Common Vaults by Version:
| Vault Name | Version | Deposit Tokens | Notes |
|---|---|---|---|
| Upshift USDC | evm-1 | USDC only | Standard deposit |
| Upshift USDT | evm-1 | USDT only | Standard deposit |
| Treehouse Growth | evm-1 | wstETH, WETH, ETH | Has adapters |
| Kelp TAC rsETH | evm-1 | rsETH, stETH, ETHx, WETH, ETH | Has adapters |
| Wild USD | evm-2 | USDC, USDT, DAI | Multi-asset |
| BTC Multi-Token | evm-1 | WBTC, USDC (via swap) | Has swap adapter |
Decision Tree
Do you have a depositAsset parameter?
│
├─ NO → Standard deposit with underlying token
│ ├─ EVM-0/1: 2-param deposit
│ └─ EVM-2: 3-param deposit with first depositAsset
│
└─ YES → Is depositAsset different from underlying?
│
├─ NO → Standard deposit (same as above)
│
└─ YES → Is vault EVM-2 with depositAsset whitelisted?
│
├─ YES → Multi-asset deposit (3-param)
│
└─ NO → Adapter deposit
├─ Native token? → Wrapper adapter
├─ Different ERC20? → Swap adapter
└─ Wrapped version? → Wrapper adapterAdapter Deposits
Deposit with alternative tokens beyond the vault's underlying asset.
Check Available Tokens
const vault = await sdk.getVault({ vault: vaultAddress, chainId: 1 });
console.log('Supported deposit tokens:');
vault.depositAssets.forEach((asset) => {
console.log(`- ${asset.symbol}: ${asset.address}`);
});Deposit with Alternative Token
// Get vault info
const vault = await sdk.getVault({
vault: '0x5Fde59415625401278c4d41C6beFCe3790eb357f', // Treehouse
chainId: 1,
});
// Deposit WETH instead of wstETH
const txHash = await sdk.evm.vaultDeposit({
target: vault.address,
wallet: userAddress,
amount: '1.0',
depositAsset: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
chainId: 1,
wait: true,
});Deposit Native ETH
// Deposit native ETH (zero address)
await sdk.evm.vaultDeposit({
target: '0x5Fde59415625401278c4d41C6beFCe3790eb357f',
wallet: userAddress,
amount: '1.0',
depositAsset: '0x0000000000000000000000000000000000000000', // Native ETH
chainId: 1,
poolName: 'Treehouse Growth',
wait: true,
});Supported Adapter Vaults
| Vault | Supported Tokens | Type |
|---|---|---|
| Treehouse Growth | wstETH, WETH, ETH | Native deposits |
| Kelp TAC rsETH | stETH, ETHx, WETH, ETH | Native deposits |
| BTC Multi-Token | WBTC, cbBTC, tBTC | Swap adapter (Paraswap) |
| AVAX Strategy | WAVAX, AVAX | Native deposits |
Request Withdrawal
Request to withdraw tokens from a vault. Subject to lag period before claiming.
sdk.evm.vaultRequestRedeem({
target: string;
wallet: string;
amount: string | bigint | number;
wait?: boolean;
}): Promise<string>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
target | string | Yes | Vault contract address |
wallet | string | Yes | User wallet address |
amount | string | bigint | number | Yes | Amount of shares to redeem |
wait | boolean | No | Wait for confirmation |
Returns
Transaction hash as string
Example
// Request to redeem 50 vault shares
const txHash = await sdk.evm.vaultRequestRedeem({
target: '0x80E1048eDE66ec4c364b4F22C8768fc657FF6A42',
wallet: userAddress,
amount: '50',
wait: true,
});
console.log('Redemption requested:', txHash);
console.log('Wait for lag period before claiming');
// Check when you can claim
const { availableRedemptions } = await sdk.getVaultAvailableRedemptions({
vault: '0x80E1048eDE66ec4c364b4F22C8768fc657FF6A42',
wallet: userAddress,
chainId: 1,
});Behavior
The SDK automatically:
- Detects vault version
- Uses correct function signature:
- EVM-0/1:
requestRedeem(uint256, address, address)(3 params) - EVM-2:
requestRedeem(uint256, address)(2 params)
- EVM-0/1:
- Converts amount to proper decimals
- Submits transaction
Claim Redemption
Claim tokens from a completed redemption request.
sdk.evm.vaultRedeem({
target: string;
wallet: string;
wait?: boolean;
year: string;
month: string;
day: string;
receiverIndex: string;
}): Promise<string>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
target | string | Yes | Vault contract address |
wallet | string | Yes | User wallet address |
year | string | Yes | Year from redemption request |
month | string | Yes | Month from redemption request |
day | string | Yes | Day from redemption request |
receiverIndex | string | Yes | Receiver index |
wait | boolean | No | Wait for confirmation |
Returns
Transaction hash as string
Example
// Get available redemptions
const { availableRedemptions } = await sdk.getVaultAvailableRedemptions({
vault: vaultAddress,
wallet: userAddress,
chainId: 1,
});
// Claim first available redemption
if (availableRedemptions.length > 0) {
const redemption = availableRedemptions[0];
const txHash = await sdk.evm.vaultRedeem({
target: vaultAddress,
wallet: userAddress,
year: redemption.year.raw,
month: redemption.month.raw,
day: redemption.day.raw,
receiverIndex: '0',
wait: true,
});
console.log('Claimed:', redemption.amount.normalized, 'tokens');
}Token Approval
Approve vault to spend tokens. Usually called automatically by vaultDeposit.
sdk.evm.vaultApprove({
target: string;
wallet: string;
amount: string | bigint | number;
wait?: boolean;
}): Promise<string | undefined>Returns
- Transaction hash if approval was needed
undefinedif allowance already sufficient
Example
// Manually approve before deposit
const txHash = await sdk.evm.vaultApprove({
target: vaultAddress,
wallet: userAddress,
amount: '1000',
wait: true,
});
if (txHash) {
console.log('Approval tx:', txHash);
} else {
console.log('Already approved');
}Check Allowance
Check current token allowance for a vault.
sdk.evm.vaultAllowance({
target: string;
wallet: string;
}): Promise<INormalizedNumber>Example
const allowance = await sdk.evm.vaultAllowance({
target: vaultAddress,
wallet: userAddress,
});
console.log('Current allowance:', allowance.normalized);
if (BigInt(allowance.raw) < BigInt(depositAmount)) {
console.log('Need to approve more');
}Examples
Complete Deposit Flow
// 1. Get vault and check options
const vault = await sdk.getVault({ vault: vaultAddress, chainId: 1 });
console.log('Deposit options:');
vault.depositAssets.forEach((asset) => {
console.log(`- ${asset.symbol}`);
});
// 2. Check if vault accepts deposits
if (vault.isDepositPaused) {
throw new Error('Vault deposits are paused');
}
// 3. Check user balance
const tokenContract = new ethers.Contract(
vault.depositAssets[0].address,
['function balanceOf(address) view returns (uint256)'],
provider,
);
const balance = await tokenContract.balanceOf(userAddress);
// 4. Deposit
const txHash = await sdk.evm.vaultDeposit({
target: vault.address,
wallet: userAddress,
amount: '100',
wait: true,
});
console.log('Success:', txHash);Complete Withdrawal Flow
// 1. Check user position
const position = await sdk.getVaultPositions({
vault: vaultAddress,
wallet: userAddress,
chainId: 1,
});
if (position[0].walletBalance.raw === '0') {
throw new Error('No balance to withdraw');
}
// 2. Request redemption
const requestTx = await sdk.evm.vaultRequestRedeem({
target: vaultAddress,
wallet: userAddress,
amount: '50',
wait: true,
});
console.log('Redemption requested:', requestTx);
// 3. Wait for lag period...
await new Promise((resolve) => setTimeout(resolve, vault.lagDuration * 1000));
// 4. Check if ready to claim
const { availableRedemptions } = await sdk.getVaultAvailableRedemptions({
vault: vaultAddress,
wallet: userAddress,
chainId: 1,
});
// 5. Claim
if (availableRedemptions.length > 0) {
const redemption = availableRedemptions[0];
const claimTx = await sdk.evm.vaultRedeem({
target: vaultAddress,
wallet: userAddress,
year: redemption.year.raw,
month: redemption.month.raw,
day: redemption.day.raw,
receiverIndex: '0',
wait: true,
});
console.log('Claimed:', claimTx);
}Multi-Asset Vault Deposit
// Get EVM-2 vault
const vault = await sdk.getVault({
vault: '0x18EE038C114a07f4B08b420fb1E4149a4F357249',
chainId: 1,
});
console.log('Vault version:', vault.version); // "evm-2"
console.log('Deposit assets:', vault.depositAssets.length);
// Deposit any whitelisted asset
const selectedAsset = vault.depositAssets[0];
const txHash = await sdk.evm.vaultDeposit({
target: vault.address,
wallet: userAddress,
amount: '100',
depositAsset: selectedAsset.address, // Required for evm-2
chainId: 1,
wait: true,
});Error Handling
try {
await sdk.evm.vaultDeposit({
target: vaultAddress,
wallet: userAddress,
amount: '100',
wait: true,
});
} catch (error) {
if (error.message.includes('insufficient balance')) {
console.error('Not enough tokens');
} else if (error.message.includes('Deposit failed')) {
console.error('Transaction reverted');
} else if (error.message.includes('user rejected')) {
console.error('User cancelled transaction');
} else {
console.error('Error:', error.message);
}
}Best Practices
1. Always Check Vault Status
const vault = await sdk.getVault({ vault, chainId });
if (vault.isDepositPaused) {
throw new Error('Deposits are currently paused');
}
if (vault.isWithdrawalPaused) {
throw new Error('Withdrawals are currently paused');
}2. Verify Deposit Cap
const vault = await sdk.getVault({ vault, chainId });
const remaining = BigInt(vault.maxSupply.raw) - BigInt(vault.totalSupply.raw);
console.log(
'Remaining capacity:',
ethers.formatUnits(remaining, vault.decimals),
);3. Show User Expected Output
// For standard deposits, use previewDeposit
const vaultContract = new ethers.Contract(
vaultAddress,
['function previewDeposit(uint256) view returns (uint256)'],
provider,
);
const expectedShares = await vaultContract.previewDeposit(
ethers.parseUnits('100', vault.decimals),
);
console.log(
'You will receive:',
ethers.formatUnits(expectedShares, vault.decimals),
'shares',
);