NestDevelopers
Borrow nUSD

Deposit collateral

Initialize a borrow position and deposit a supported collateral token.

A deposit creates the owner's vault PDA if needed and transfers collateral into the canonical market vault. It does not create debt and does not require an oracle update.

Requirements

  • Load the client from Project setup.
  • Select a market by its unique symbol, not its display ticker.
  • Read the collateral mint's configured decimals.
  • Confirm the owner has enough tokens in the associated token account.
  • Read the live collateral config and reject paused deposits or insufficient cap.

TypeScript example

deposit-collateral.ts
import { BN } from "@coral-xyz/anchor";
import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
import { getAccount } from "@solana/spl-token";
import {
  type NestClient,
  ata,
  borrowVaultPda,
  marketBySymbol,
  simulateSignSend,
  toBaseUnits,
} from "../nest-client";

export async function depositCollateral(
  client: NestClient,
  symbol: string,
  userAmount: string,
) {
  const owner = client.wallet.publicKey;
  const market = marketBySymbol(client, symbol);
  const coreProgramId = new PublicKey(client.deployment.programs.nestCore);
  const protocol = new PublicKey(client.deployment.accounts.protocol);
  const collateralConfig = new PublicKey(market.collateralConfig);
  const collateralMint = new PublicKey(market.mint);
  const collateralVault = new PublicKey(market.collateralVault);
  const collateralTokenProgram = new PublicKey(market.tokenProgram);
  const ownerCollateralAccount = ata(collateralMint, owner, collateralTokenProgram);
  const vault = borrowVaultPda(coreProgramId, owner, collateralConfig);
  const amount = toBaseUnits(userAmount, market.decimals);
  if (amount <= 0n) throw new Error("Deposit amount must be positive");

  // Validate the manifest against current on-chain configuration.
  const config = await client.core.account.collateralConfig.fetch(collateralConfig);
  if (!config.collateralMint.equals(collateralMint)) throw new Error("Collateral mint mismatch");
  if (!config.collateralVault.equals(collateralVault)) throw new Error("Collateral vault mismatch");
  if (!config.tokenProgram.equals(collateralTokenProgram)) throw new Error("Token program mismatch");
  if (config.collateralDecimals !== market.decimals) throw new Error("Collateral decimals mismatch");
  if (config.depositsPaused) throw new Error(`${symbol} deposits are paused`);

  const totalAfter = BigInt(config.totalDepositsRaw.toString()) + amount;
  if (totalAfter > BigInt(config.depositCapRaw.toString())) {
    throw new Error(`${symbol} deposit cap would be exceeded`);
  }

  const ownerToken = await getAccount(
    client.connection,
    ownerCollateralAccount,
    "confirmed",
    collateralTokenProgram,
  );
  if (ownerToken.amount < amount) {
    throw new Error(`Insufficient ${symbol}: need ${amount}, have ${ownerToken.amount}`);
  }

  const transaction = new Transaction();
  const existingVault = await client.core.account.vault.fetchNullable(vault);
  if (!existingVault) {
    transaction.add(await client.core.methods
      .initializeVault()
      .accountsStrict({
        collateralConfig,
        vault,
        owner,
        systemProgram: SystemProgram.programId,
      })
      .instruction());
  }

  transaction.add(await client.core.methods
    .deposit(new BN(amount.toString()))
    .accountsStrict({
      protocol,
      collateralConfig,
      vault,
      collateralMint,
      ownerCollateralAccount,
      collateralVault,
      owner,
      collateralTokenProgram,
    })
    .instruction());

  const collateralBefore = existingVault
    ? BigInt(existingVault.collateralRaw.toString())
    : 0n;
  const signature = await simulateSignSend(client, transaction);

  // Do not trust submission alone. Verify the position account changed.
  const vaultAfter = await client.core.account.vault.fetch(vault);
  const collateralAfter = BigInt(vaultAfter.collateralRaw.toString());
  if (collateralAfter !== collateralBefore + amount) {
    throw new Error(`Deposit verification failed for ${signature}`);
  }

  return { signature, vault, collateralRaw: collateralAfter };
}

Errors

  • Paused or CollateralPaused: the protocol or market is not accepting deposits.
  • DepositCapExceeded: the market has insufficient remaining deposit capacity.
  • Token-account constraint failure: mint, owner, token program, or custody vault does not match the collateral config.
  • Insufficient token balance: the wallet cannot transfer the requested raw amount.

After confirmation, move to Mint nUSD.

On this page