Skip to content

Deposit & Borrow (T1 Vault)

Function: operate()

Deposits collateral and borrows debt from a T1 Fluid vault in a single transaction.

  1. Collateral Types:

    • ERC20 Tokens:

      • If approval is needed, you must call approve(vaultAddress, amount) on the token contract first.
      • Then call operate with value: 0.
    • Native Tokens (ETH):

      • No approval is needed.
      • Send the collateral amount as the value of the operate transaction.
  2. Open or Update Position:

    • To open a new position, use nftId = 0. The transaction will mint a new NFT to your address.
    • To update an existing position, use the specific nftId for that position.
    • Transaction data:
      typescript
      {
        to: vaultAddress,
        data: encodeFunctionData({
          abi: vaultT1Abi,
          functionName: 'operate',
          args: [
             nftId,            // 0 for new position, or the specific NFT ID
             collateralAmount, // Positive value to deposit collateral (uint256 as int256)
             borrowAmount,     // Positive value to borrow debt (uint256 as int256)
             accountAddress    // Address to receive the NFT/borrowed tokens
          ]
        }),
        value: isNative ? collateralAmount : 0n // Send value if depositing native ETH
      }
  3. Operate ABI:

    typescript
    export const vaultT1Abi = [
      {
        name: "operate",
        type: "function",
        stateMutability: "payable",
        inputs: [
          { name: "nftId_", type: "uint256" },
          { name: "newCol_", type: "int256" },
          { name: "newDebt_", type: "int256" },
          { name: "to_", type: "address" },
        ],
        outputs: [
          { name: "nftId", type: "uint256" },
          { name: "supplyAmt", type: "int256" },
          { name: "borrowAmt", type: "int256" },
        ],
      },
    ];

Flow:

User → approve(collateral) → operate(0, col, debt, ...) → Position Created

Full deposit & borrow example

ts
/**
 * Example: Deposit WETH, borrow USDC on Polygon (WETH/USDC vault)
 *
 * Flow: (1) Approve vault to spend WETH (if col is ERC20), (2) operate(0, collateralAmount, borrowAmount, to).
 * Set PRIVATE_KEY and RPC_URL in .env.
 *
 * Run: pnpm run borrow:t1-deposit-borrow -- --network polygon
 */

import { formatUnits, encodeFunctionData, erc20Abi, parseUnits } from "viem";
import vaultT1Abi from "../shared/abis/vaultT1Abi";
import {
  account,
  chain,
  publicClient,
  walletClient,
} from "../shared/config.js";

// WETH/USDC vault contract address and WETH address on Polygon
const VAULT_WETH_USDC = "0xeAbBfca72F8a8bf14C4ac59e69ECB2eB69F0811C";
const POLYGON_WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";

// In this example, col is not native token.
const isColNative = false;

async function main() {
  const collateralAmount = parseUnits("0.001", 18); // 0.001 wEth
  const borrowAmount = parseUnits("1", 6); // 1 USDC

  console.log("Borrow: deposit WETH, borrow USDC (Polygon, WETH/USDC vault)");
  console.log("  Vault:", VAULT_WETH_USDC);
  console.log("  Collateral:", formatUnits(collateralAmount, 18), "WETH");
  console.log("  Borrow:", formatUnits(borrowAmount, 6), "USDC");

  // Step 1 - Approve the vault to spend WETH (skip if col is native – send via value instead)
  if (!isColNative) {
    const approveData = encodeFunctionData({
      abi: erc20Abi,
      functionName: "approve",
      args: [VAULT_WETH_USDC, collateralAmount],
    });
    const approveHash = await walletClient.sendTransaction({
      to: POLYGON_WETH,
      data: approveData,
      account,
    });

    console.log("  Approve tx:", approveHash);
    console.log(
      "Explorer:",
      `${chain.blockExplorers?.default?.url}/tx/${approveHash}`,
    );

    const approveReceipt = await publicClient.waitForTransactionReceipt({
      hash: approveHash,
    });
    if (approveReceipt.status !== "success") {
      console.error("Approve tx reverted");
      process.exit(1);
    }
  }

  // Step 2 - Call operate() to deposit collateral and borrow
  const operateData = encodeFunctionData({
    abi: vaultT1Abi,
    functionName: "operate",
    args: [0n, collateralAmount, borrowAmount, account.address], // NFT_ID=0 (new position)
  });

  const hash = await walletClient.sendTransaction({
    to: VAULT_WETH_USDC,
    data: operateData,
    value: isColNative ? collateralAmount : 0n,
    account,
  });

  console.log("  Operate tx:", hash);
  console.log("Explorer:", `${chain.blockExplorers?.default?.url}/tx/${hash}`);

  // Wait for the operate transaction to be confirmed and check the status
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
  if (receipt.status !== "success") {
    console.error("Operate tx reverted");
    process.exit(1);
  }
  console.log("Position opened.");
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});