Version: 1.0.0
Network: Solana Devnet
Program ID: 4EFWHK5D9m5UL1KjW9xbb5ZHupGbM3AZDvQgYiJYt2c9
- System Architecture
- Smart Contract Documentation
- SPL Token Integration
- Backend Service Documentation
- Security Analysis
Non-custodial collateral management system for a decentralized perpetual futures exchange on Solana. Users deposit USDT into program-controlled vaults (PDAs) that can be locked for margin requirements during trading.
| Component | Technology |
|---|---|
| Smart Contract | Rust + Anchor 0.30.1 |
| Backend | Rust + Axum 0.7 + Tokio |
| Database | PostgreSQL + sqlx |
| Blockchain | Solana Devnet |
┌─────────────────────────────────────────────────────────────────────────┐
│ COLLATERAL VAULT SYSTEM │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ VaultAuthority (Singleton PDA) │ │
│ │ Seeds: ["authority"] │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ admin: Pubkey (32 bytes) ││ │
│ │ │ authorized_programs: Vec (4 + 32*n bytes) ││ │
│ │ │ bump: u8 (1 byte) ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ Controls Lock/Unlock/Transfer │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ CollateralVault (Per-User PDA) │ │
│ │ Seeds: ["vault", user_pubkey] │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ owner: Pubkey (32 bytes) ││ │
│ │ │ token_account: Pubkey (32 bytes) ││ │
│ │ │ total_balance: u64 (8 bytes) ││ │
│ │ │ locked_balance: u64 (8 bytes) ││ │
│ │ │ available_balance: u64 (8 bytes) ││ │
│ │ │ total_deposited: u64 (8 bytes) ││ │
│ │ │ total_withdrawn: u64 (8 bytes) ││ │
│ │ │ created_at: i64 (8 bytes) ││ │
│ │ │ bump: u8 (1 byte) ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Vault Token Account (ATA) │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ mint: USDT_MINT ││ │
│ │ │ owner: vault_pda (PDA authority) ││ │
│ │ │ amount: actual token balance ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ INVARIANT: available_balance = total_balance - locked_balance │
└─────────────────────────────────────────────────────────────────────────┘
| Account | Seeds | Derivation Code |
|---|---|---|
| Vault PDA | ["vault", user_pubkey] |
Pubkey::find_program_address(&[b"vault", user.as_ref()], &program_id) |
| Authority PDA | ["authority"] |
Pubkey::find_program_address(&[b"authority"], &program_id) |
| Vault ATA | Standard ATA | get_associated_token_address(&vault_pda, &usdt_mint) |
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ User │ │ Backend │ │ Solana │ │ SPL Token │
│ Wallet │ │ Service │ │ Program │ │ Program │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │
│ 1. POST /deposit │ │ │
│ ─────────────────► │ │ │
│ │ │ │
│ 2. Unsigned Tx │ │ │
│ ◄───────────────── │ │ │
│ │ │ │
│ 3. Sign with Wallet │ │
│ ─────────────────────────────────────► │ │
│ │ │ │
│ │ │ 4. CPI: Transfer │
│ │ │ ─────────────────► │
│ │ │ │
│ │ │ 5. Tokens Moved │
│ │ │ ◄───────────────── │
│ │ │ │
│ │ │ 6. Update Vault │
│ │ │ State │
│ │ │ │
│ 7. Tx Confirmed │ │ │
│ ◄───────────────────────────────────── │ │
│ │ │ │
│ 8. POST /confirm │ │ │
│ ─────────────────► │ │ │
│ │ │ │
│ │ 9. Update DB │ │
│ │ │ │
│ 10. Success │ │ │
│ ◄───────────────── │ │ │
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ User │ │ Backend │ │ Solana │ │ SPL Token │
│ Wallet │ │ Service │ │ Program │ │ Program │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │
│ 1. POST /withdraw │ │ │
│ ─────────────────► │ │ │
│ │ │ │
│ │ 2. Check balance │ │
│ │ │ │
│ 3. Unsigned Tx │ │ │
│ ◄───────────────── │ │ │
│ │ │ │
│ 4. Sign with Wallet │ │
│ ─────────────────────────────────────► │ │
│ │ │ │
│ │ │ 5. Verify Owner │
│ │ │ 6. Check Balance │
│ │ │ │
│ │ │ 7. CPI: Transfer │
│ │ │ (PDA Signs) │
│ │ │ ─────────────────► │
│ │ │ │
│ │ │ 8. Tokens Moved │
│ │ │ ◄───────────────── │
│ │ │ │
│ 9. Tx Confirmed │ │ │
│ ◄───────────────────────────────────── │ │
│ │ │ │
│ 10. POST /confirm │ │ │
│ ─────────────────► │ │ │
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Position │ │ Vault │ │ Vault │ │ Backend │
│ Manager │ │ Authority │ │ Program │ │ Service │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │
│ 1. User Opens Position │ │
│ │ │ │
│ 2. CPI: lock_collateral │ │
│ ─────────────────────────────────────► │ │
│ │ │ │
│ │ 3. Verify caller │ │
│ │ in whitelist │ │
│ │ ◄───────────────── │ │
│ │ │ │
│ │ 4. Authorized ✓ │ │
│ │ ─────────────────► │ │
│ │ │ │
│ │ │ 5. Update Vault: │
│ │ │ locked += amt │
│ │ │ available -= amt│
│ │ │ │
│ 6. Lock Success │ │ │
│ ◄───────────────────────────────────── │ │
│ │ │ │
│ │ │ │ 7. Update DB
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Liquidation │ │ Vault │ │ Vault │
│ Engine │ │ Program │ │ Accounts │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
│ 1. Detect Under- │ │
│ collateralized │ │
│ │ │
│ 2. CPI: transfer_collateral │
│ ─────────────────► │ │
│ │ │
│ │ 3. Verify Auth │
│ │ │
│ │ 4. From Vault: │
│ │ total -= amt │
│ │ available -= amt│
│ │ ─────────────────► │
│ │ │
│ │ 5. To Vault: │
│ │ total += amt │
│ │ available += amt│
│ │ ─────────────────► │
│ │ │
│ 6. Transfer Done │ │
│ ◄───────────────── │ │
┌─────────────────────────────────────────────────────────────────────────────┐
│ UNTRUSTED ZONE │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ External Users Network Traffic Malicious Actors │ │
│ │ • Wallet connections • HTTP requests • Replay attacks │ │
│ │ • User inputs • WebSocket msgs • Overflow attacks │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ VALIDATION LAYER │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Input Validation Signature Verification Rate Limiting │ │
│ │ • Pubkey format • Ed25519 signatures • Request limits │ │
│ │ • Amount > 0 • Transaction signing • Connection caps │ │
│ │ • Balance checks • Owner verification │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TRUSTED ZONE │
│ ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────────┐ │
│ │ Backend Service │ │ Smart Contract │ │ Solana Runtime │ │
│ │ • Tx building │ │ • PDA custody │ │ • BPF execution │ │
│ │ • State sync │ │ • Access control│ │ • Signature verify │ │
│ │ • No key access │ │ • Atomic updates│ │ • Account ownership │ │
│ └───────────────────┘ └───────────────────┘ └───────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
#[account]
pub struct CollateralVault {
pub owner: Pubkey, // 32 bytes - Wallet owner
pub token_account: Pubkey, // 32 bytes - Associated token account
pub total_balance: u64, // 8 bytes - Total USDT in vault
pub locked_balance: u64, // 8 bytes - Locked for positions
pub available_balance: u64, // 8 bytes - Available for withdrawal
pub total_deposited: u64, // 8 bytes - Lifetime deposits
pub total_withdrawn: u64, // 8 bytes - Lifetime withdrawals
pub created_at: i64, // 8 bytes - Creation timestamp
pub bump: u8, // 1 byte - PDA bump seed
}
// Total: 8 (discriminator) + 113 = 121 bytes#[account]
pub struct VaultAuthority {
pub admin: Pubkey, // 32 bytes - Admin who can add programs
pub authorized_programs: Vec<Pubkey>, // 4 + 32*n bytes - Whitelisted programs
pub bump: u8, // 1 byte - PDA bump seed
}
// Max 10 authorized programs| Instruction | Signer | Description |
|---|---|---|
initialize_vault |
User | Create PDA vault + token account |
deposit |
User | Transfer USDT from user to vault |
withdraw |
User | Transfer USDT from vault to user |
lock_collateral |
Authorized Program | Lock funds for margin |
unlock_collateral |
Authorized Program | Release locked funds |
transfer_collateral |
Authorized Program | Transfer between vaults |
initialize_authority |
Admin | Create authority singleton |
add_authorized_program |
Admin | Whitelist a program |
| Account | Type | Description |
|---|---|---|
user |
Signer, Mut | Wallet owner, pays rent |
vault |
PDA, Init | New vault account |
usdt_mint |
Account | USDT token mint |
vault_token_account |
ATA, Init | Vault's token account |
system_program |
Program | System program |
token_program |
Program | SPL Token program |
associated_token_program |
Program | ATA program |
| Account | Type | Description |
|---|---|---|
user |
Signer, Mut | Depositor |
vault |
PDA, Mut | User's vault |
user_token_account |
TokenAccount, Mut | User's USDT account |
vault_token_account |
TokenAccount, Mut | Vault's USDT account |
usdt_mint |
Account | USDT mint |
token_program |
Program | SPL Token program |
| Account | Type | Description |
|---|---|---|
user |
Signer, Mut | Withdrawer (must be owner) |
vault |
PDA, Mut | User's vault (signs via seeds) |
user_token_account |
TokenAccount, Mut | User's USDT account |
vault_token_account |
TokenAccount, Mut | Vault's USDT account |
usdt_mint |
Account | USDT mint |
token_program |
Program | SPL Token program |
| Account | Type | Description |
|---|---|---|
authority |
Signer | Must be in authorized_programs list |
vault_authority |
PDA | Authority singleton |
vault |
Account, Mut | Target vault |
| Account | Type | Description |
|---|---|---|
authority |
Signer | Must be authorized |
vault_authority |
PDA | Authority singleton |
from_vault |
Account, Mut | Source vault |
to_vault |
Account, Mut | Destination vault |
// Vault PDA derivation
impl CollateralVault {
pub const SEED_PREFIX: &'static [u8] = b"vault";
}
// Seeds: ["vault", user_pubkey]
// Authority PDA derivation
impl VaultAuthority {
pub const SEED_PREFIX: &'static [u8] = b"authority";
}
// Seeds: ["authority"]// Constraint validation for vault ownership
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump = vault.bump,
constraint = vault.owner == user.key() @ VaultError::UnauthorizedCaller,
)]
pub vault: Account<'info, CollateralVault>,
// Authority whitelist check in instruction logic
let caller = ctx.accounts.authority.key();
require!(
ctx.accounts.vault_authority.authorized_programs.contains(&caller),
VaultError::UnauthorizedCaller
);| Code | Name | Description |
|---|---|---|
| 6000 | InvalidAmount | Amount must be > 0 |
| 6001 | InsufficientAvailableBalance | Not enough unlocked funds |
| 6002 | InsufficientLockedBalance | Not enough locked funds |
| 6003 | UnauthorizedCaller | Caller not authorized |
| 6004 | Overflow | Arithmetic overflow |
| 6005 | InvalidTokenAccount | Token account mismatch |
| 6006 | MaxAuthorizedProgramsReached | Max 10 programs |
| 6007 | ProgramAlreadyAuthorized | Duplicate program |
token::transfer(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
Transfer {
from: ctx.accounts.user_token_account.to_account_info(),
to: ctx.accounts.vault_token_account.to_account_info(),
authority: ctx.accounts.user.to_account_info(),
},
),
amount,
)?;let user_key = ctx.accounts.user.key();
let seeds = &[b"vault", user_key.as_ref(), &[vault.bump]];
token::transfer(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
Transfer {
from: ctx.accounts.vault_token_account.to_account_info(),
to: ctx.accounts.user_token_account.to_account_info(),
authority: vault.to_account_info(),
},
&[seeds],
),
amount,
)?;// Vault token account initialization (ATA)
#[account(
init,
payer = user,
associated_token::mint = usdt_mint,
associated_token::authority = vault,
)]
pub vault_token_account: Account<'info, TokenAccount>,
// User token account validation
#[account(
mut,
constraint = user_token_account.mint == usdt_mint.key() @ VaultError::InvalidTokenAccount,
constraint = user_token_account.owner == user.key() @ VaultError::UnauthorizedCaller,
)]
pub user_token_account: Account<'info, TokenAccount>,The program uses anchor_spl::token for all token operations:
use anchor_spl::token::{self, Token, TokenAccount, Transfer};
// Standard CPI (user authority)
token::transfer(CpiContext::new(token_program, transfer_accounts), amount)?;
// PDA-signed CPI (vault authority)
token::transfer(CpiContext::new_with_signer(token_program, transfer_accounts, signer_seeds), amount)?;// Balance validation before transfer
require!(amount > 0, VaultError::InvalidAmount);
require!(amount <= vault.available_balance, VaultError::InsufficientAvailableBalance);
// Checked arithmetic to prevent overflow
vault.total_balance = vault.total_balance.checked_add(amount).ok_or(VaultError::Overflow)?;
vault.available_balance = vault.available_balance.checked_sub(amount).ok_or(VaultError::Overflow)?;backend/src/
├── main.rs # Entry point, server setup
├── config.rs # Environment configuration
├── api/
│ ├── mod.rs # API module exports
│ ├── routes.rs # REST endpoint handlers
│ └── websocket.rs # WebSocket event handlers
├── vault_manager.rs # Core vault business logic
├── vault_monitor.rs # TVL monitoring and analytics
├── balance_tracker.rs # Real-time balance tracking
├── tx_builder.rs # Transaction construction
├── cpi_manager.rs # CPI helper utilities
├── solana_types.rs # Solana type definitions
└── db/
├── mod.rs # Database module exports
├── models.rs # Data structures
└── queries.rs # SQL operations
| Method | Endpoint | Description |
|---|---|---|
| POST | /vault/initialize |
Build unsigned vault init tx |
| POST | /vault/deposit |
Build unsigned deposit tx |
| POST | /vault/withdraw |
Build unsigned withdraw tx |
| POST | /vault/confirm |
Confirm on-chain transaction |
| POST | /vault/lock |
Lock collateral (internal) |
| POST | /vault/unlock |
Unlock collateral (internal) |
| GET | /vault/balance/:user |
Get vault balance |
| GET | /vault/transactions/:user |
Get transaction history |
| GET | /vault/tvl |
Get total value locked |
POST /vault/initialize
// Request
{ "user_pubkey": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU" }
// Response
{
"success": true,
"data": {
"vault_pubkey": "9xYLm3DN87e98UYKTEqcF6kCkieTrB94UStRvKthBtV",
"vault_token_account": "...",
"unsigned_tx": {
"instructions": [...],
"required_signers": ["7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"],
"message": "Sign this transaction to initialize your vault"
}
}
}POST /vault/deposit
// Request
{ "user_pubkey": "7xKXtg2...", "amount": 1000000 }
// Response
{
"success": true,
"data": {
"unsigned_tx": {...},
"vault_pubkey": "...",
"current_balance": { "total": 0, "locked": 0, "available": 0 }
}
}POST /vault/confirm
// Request
{
"user_pubkey": "7xKXtg2...",
"tx_signature": "5KtVZ...",
"tx_type": "deposit",
"amount": 1000000
}
// Response
{
"success": true,
"data": {
"confirmed": true,
"new_balance": { "total": 1000000, "locked": 0, "available": 1000000 }
}
}GET /vault/balance/:user
{
"success": true,
"data": { "total": 1000000, "locked": 250000, "available": 750000 }
}Endpoint: ws://localhost:3000/ws/events
// Subscribe to vault updates
{ "action": "subscribe_vault", "user": "7xKXtg2..." }
// Subscribe to TVL updates
{ "action": "subscribe_tvl" }
// Event types: balance_update, deposit, withdrawal, lock, unlock, tvl_updateThe backend builds unsigned transactions for client-side signing:
pub struct TransactionBuilder {
program_id: Pubkey,
usdt_mint: Pubkey,
}
impl TransactionBuilder {
// Derive vault PDA for user
pub fn derive_vault_pda(&self, user: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[b"vault", user.as_ref()], &self.program_id)
}
// Derive associated token account
pub fn derive_ata(&self, owner: &Pubkey, mint: &Pubkey) -> Pubkey {
get_associated_token_address(owner, mint)
}
// Build deposit instruction
pub fn build_deposit(&self, user: &Pubkey, amount: u64) -> Result<BuiltTransaction> {
let (vault_pda, _) = self.derive_vault_pda(user);
let user_ata = self.derive_ata(user, &self.usdt_mint);
let vault_ata = self.derive_ata(&vault_pda, &self.usdt_mint);
// ... build instruction with accounts
}
}CREATE TABLE vaults (
id SERIAL PRIMARY KEY,
owner_pubkey VARCHAR(44) UNIQUE NOT NULL,
vault_pubkey VARCHAR(44) UNIQUE NOT NULL,
token_account_pubkey VARCHAR(44) NOT NULL,
total_balance BIGINT NOT NULL DEFAULT 0,
locked_balance BIGINT NOT NULL DEFAULT 0,
available_balance BIGINT NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);CREATE TABLE transactions (
id SERIAL PRIMARY KEY,
vault_id INTEGER REFERENCES vaults(id),
tx_signature VARCHAR(88) UNIQUE,
tx_type VARCHAR(20) NOT NULL,
amount BIGINT NOT NULL,
from_vault_pubkey VARCHAR(44),
to_vault_pubkey VARCHAR(44),
status VARCHAR(20) NOT NULL DEFAULT 'pending',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
confirmed_at TIMESTAMP
);CREATE TABLE balance_snapshots (
id SERIAL PRIMARY KEY,
vault_id INTEGER REFERENCES vaults(id),
total_balance BIGINT NOT NULL,
locked_balance BIGINT NOT NULL,
available_balance BIGINT NOT NULL,
snapshot_at TIMESTAMP NOT NULL DEFAULT NOW()
);CREATE TABLE reconciliation_logs (
id SERIAL PRIMARY KEY,
vault_id INTEGER REFERENCES vaults(id),
on_chain_balance BIGINT NOT NULL,
off_chain_balance BIGINT NOT NULL,
discrepancy BIGINT NOT NULL,
resolved BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);| Threat | Risk Level | Mitigation |
|---|---|---|
| Unauthorized fund access | Critical | PDA custody + owner signature required |
| Integer overflow | High | Checked arithmetic on all operations |
| Replay attacks | Medium | Solana's built-in tx deduplication |
| Unauthorized lock/unlock | High | Authority whitelist validation |
| Token account spoofing | High | Constraint validation on accounts |
| Front-running | Low | Atomic transactions |
| Operation | Owner | Authorized Program | Admin | Backend |
|---|---|---|---|---|
| Initialize Vault | ✅ Signs | ❌ | ❌ | Builds Tx |
| Deposit | ✅ Signs | ❌ | ❌ | Builds Tx |
| Withdraw | ✅ Signs | ❌ | ❌ | Builds Tx |
| Lock Collateral | ❌ | ✅ Signs | ❌ | Tracks State |
| Unlock Collateral | ❌ | ✅ Signs | ❌ | Tracks State |
| Transfer Collateral | ❌ | ✅ Signs | ❌ | Tracks State |
| Add Authorized Program | ❌ | ❌ | ✅ Signs | ❌ |
| Query Balance | Read Only | Read Only | Read Only | ✅ |
| Attack Vector | Mitigation |
|---|---|
| Unauthorized Withdrawal | Owner signature required + PDA ownership check |
| Unauthorized Lock/Unlock | Caller must be in authorized_programs whitelist |
| Integer Overflow | All arithmetic uses checked_* operations |
| Replay Attack | Solana's built-in transaction deduplication |
| Front-Running | Transactions are atomic; state changes are immediate |
| Token Account Mismatch | Constraints verify token account matches vault |
| Fake Authority | Authority PDA derived deterministically from seeds |
| Balance Manipulation | Invariant: available = total - locked enforced |
| Private Key Theft | Non-custodial design - backend never holds keys |
- PDA Custody: Funds held in program-controlled PDAs with no private key
- Owner Validation: Only vault owner can deposit/withdraw their funds
- Authority Whitelist: Only pre-authorized programs can lock/unlock/transfer
- Checked Arithmetic: All math uses
checked_add/checked_subto prevent overflow - Constraint Validation: Anchor constraints verify all account relationships
- Non-Custodial Design: Backend never holds private keys
- Input Validation: All pubkeys and amounts validated before processing
- Transaction Verification: Users sign and submit transactions themselves
- State Synchronization: Database mirrors on-chain state for fast queries
// Vault ownership check
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump = vault.bump,
constraint = vault.owner == user.key() @ VaultError::UnauthorizedCaller,
)]
pub vault: Account<'info, CollateralVault>,
// Token account validation
#[account(
mut,
constraint = user_token_account.mint == usdt_mint.key() @ VaultError::InvalidTokenAccount,
constraint = user_token_account.owner == user.key() @ VaultError::UnauthorizedCaller,
)]
pub user_token_account: Account<'info, TokenAccount>,
// Vault token account validation
#[account(
mut,
constraint = vault_token_account.key() == vault.token_account @ VaultError::InvalidTokenAccount,
)]
pub vault_token_account: Account<'info, TokenAccount>,| Name | Address |
|---|---|
| Collateral Vault Program | 4EFWHK5D9m5UL1KjW9xbb5ZHupGbM3AZDvQgYiJYt2c9 |
| USDT Mint (Mainnet) | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| SPL Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Associated Token Program | ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL |
DATABASE_URL=postgres://localhost/collateral_vault
SOLANA_RPC_URL=https://api.devnet.solana.com
PROGRAM_ID=4EFWHK5D9m5UL1KjW9xbb5ZHupGbM3AZDvQgYiJYt2c9
USDT_MINT=Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
SERVER_HOST=127.0.0.1
SERVER_PORT=3000| Term | Definition |
|---|---|
| PDA | Program Derived Address - deterministic address with no private key |
| CPI | Cross-Program Invocation - calling one program from another |
| ATA | Associated Token Account - deterministic token account for a wallet/mint pair |
| TVL | Total Value Locked - sum of all deposited funds across all vaults |
Smart Contract Tests (19 passing)
anchor test --provider.cluster devnetBackend API Tests
./backend/tests/api_tests.sh