Skip to main content

Deposit Assets into Upshift Vault

This guide demonstrates how to deposit assets into an Upshift vault. The Upshift vault implements an ERC-4626 style tokenized vault, allowing users to deposit assets (e.g., FXRP) and receive LP tokens (vault shares) in return.

Depositing assets is the process of transferring them to the vault and receiving LP tokens that represent your proportional ownership of the vault's assets.

Prerequisites

Upshift Vault Deposit Script

The following script demonstrates how to deposit assets into the Upshift vault:

scripts/upshift/deposit.ts
/**
* Upshift Tokenized Vault Deposit Script
*
* This script deposits assets into the Upshift Tokenized Vault.
*
*/

import { web3 } from "hardhat";
import { parseUnits, formatUnits } from "ethers";

import type { ITokenizedVaultInstance } from "../../typechain-types/contracts/upshift/ITokenizedVault";
import type { IERC20Instance } from "../../typechain-types/@openzeppelin/contracts/token/ERC20/IERC20";

const VAULT_ADDRESS = "0x24c1a47cD5e8473b64EAB2a94515a196E10C7C81";
const DEPOSIT_AMOUNT = "1";

const ITokenizedVault = artifacts.require("ITokenizedVault");
const IERC20 = artifacts.require("IERC20");
const IFAsset = artifacts.require("IFAsset");

async function getReferenceAssetInfo(vault: ITokenizedVaultInstance) {
const referenceAsset = await vault.asset();
const refAsset = await IFAsset.at(referenceAsset);
const decimals = Number(await refAsset.decimals());
const symbol = await refAsset.symbol();

console.log("\nReference Asset (asset depositing):", referenceAsset);

return { referenceAsset, refAsset, decimals, symbol };
}

async function checkBalance(
refAsset: IERC20Instance,
userAddress: string,
depositAmount: bigint,
decimals: number,
symbol: string,
) {
const balance = await refAsset.balanceOf(userAddress);
console.log(
`Balance: ${formatUnits(balance.toString(), decimals)} ${symbol}`,
);

if (BigInt(balance.toString()) < depositAmount) {
console.log("Insufficient balance!");
return false;
}
return true;
}

async function checkAndApproveAllowance(
refAsset: IERC20Instance,
userAddress: string,
depositAmount: bigint,
decimals: number,
symbol: string,
) {
const allowance = await refAsset.allowance(userAddress, VAULT_ADDRESS);
console.log(
`Current Allowance: ${formatUnits(allowance.toString(), decimals)} ${symbol}`,
);

if (BigInt(allowance.toString()) < depositAmount) {
console.log(
`\nApproving vault to spend ${DEPOSIT_AMOUNT} ${symbol} tokens`,
);
const approveTx = await refAsset.approve(
VAULT_ADDRESS,
depositAmount.toString(),
);
console.log("Approval Tx:", approveTx.tx);
}
}

async function previewDeposit(
vault: ITokenizedVaultInstance,
referenceAsset: string,
depositAmount: bigint,
decimals: number,
) {
const preview = await vault.previewDeposit(
referenceAsset,
depositAmount.toString(),
);
const expectedShares = preview[0];
const amountInRefTokens = preview[1];

console.log(
`\nExpected Shares: ${formatUnits(expectedShares.toString(), decimals)}`,
);
console.log(
`Amount in Reference Tokens: ${formatUnits(amountInRefTokens.toString(), decimals)}`,
);

return { expectedShares };
}

async function getLPTokenInfo(
vault: ITokenizedVaultInstance,
userAddress: string,
decimals: number,
) {
const lpTokenAddress = await vault.lpTokenAddress();
const lpToken: IERC20Instance = await IERC20.at(lpTokenAddress);
const lpBalanceBefore = await lpToken.balanceOf(userAddress);

console.log(
`LP Balance Before: ${formatUnits(lpBalanceBefore.toString(), decimals)}`,
);

return { lpToken, lpBalanceBefore };
}

async function executeDeposit(
vault: ITokenizedVaultInstance,
referenceAsset: string,
depositAmount: bigint,
userAddress: string,
) {
const depositTx = await vault.deposit(
referenceAsset,
depositAmount.toString(),
userAddress,
);
console.log(
"\nDeposit: (tx:",
depositTx.tx,
", block:",
depositTx.receipt.blockNumber,
")",
);
}

async function verifyDeposit(
lpToken: IERC20Instance,
userAddress: string,
lpBalanceBefore: { toString(): string },
decimals: number,
) {
console.log("\nVerifying deposit...");

const lpBalanceAfter = await lpToken.balanceOf(userAddress);
const sharesReceived =
BigInt(lpBalanceAfter.toString()) - BigInt(lpBalanceBefore.toString());

console.log(
`LP Balance After: ${formatUnits(lpBalanceAfter.toString(), decimals)}`,
);
console.log(
`Shares Received: ${formatUnits(sharesReceived.toString(), decimals)}`,
);
}

async function main() {
// 1. Initialize: Get user account from Hardhat network
const accounts = await web3.eth.getAccounts();
const userAddress = accounts[0];

console.log("DEPOSIT TO VAULT\n");
console.log("Vault Address:", VAULT_ADDRESS);
console.log("User Address:", userAddress);

// 2. Connect to the vault contract instance
const vault: ITokenizedVaultInstance =
await ITokenizedVault.at(VAULT_ADDRESS);

// 3. Get reference asset info
const { referenceAsset, refAsset, decimals, symbol } =
await getReferenceAssetInfo(vault);

// 4. Convert deposit amount from human-readable to token units
const depositAmount = parseUnits(DEPOSIT_AMOUNT, decimals);
console.log(
`\nDeposit Amount: ${DEPOSIT_AMOUNT} ${symbol} (${depositAmount.toString()})`,
);

// 5. Check user balance
const hasBalance = await checkBalance(
refAsset,
userAddress,
depositAmount,
decimals,
symbol,
);
if (!hasBalance) return;

// 6. Check and approve allowance
await checkAndApproveAllowance(
refAsset,
userAddress,
depositAmount,
decimals,
symbol,
);

// 7. Preview deposit
await previewDeposit(vault, referenceAsset, depositAmount, decimals);

// 8. Get LP token info before deposit
const { lpToken, lpBalanceBefore } = await getLPTokenInfo(
vault,
userAddress,
decimals,
);

// 9. Execute deposit
await executeDeposit(vault, referenceAsset, depositAmount, userAddress);

// 10. Verify deposit
await verifyDeposit(lpToken, userAddress, lpBalanceBefore, decimals);
}

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

Script Breakdown

The main() function executes the following steps:

  1. Initialize: Gets the user account and logs the vault and user addresses.
  2. Connect to vault: Creates an instance of the Upshift vault contract.
  3. Get reference asset info: Retrieves the vault's reference asset (FXRP) address, symbol, and decimals.
  4. Calculate deposit amount: Converts the desired amount into the correct units based on decimals.
  5. Check balance: Verifies the user has sufficient balance to cover the deposit.
  6. Approve allowance: Approves the vault to spend the deposit amount if needed.
  7. Preview deposit: Calls previewDeposit() to see the expected shares and amount in reference tokens.
  8. Get LP token info: Records the LP token balance before the deposit.
  9. Execute deposit: Calls deposit() to transfer assets and mint LP tokens.
  10. Verify deposit: Confirms the deposit by checking the new LP token balance and shares received.

Running the Script

To run the Upshift vault deposit script:

  1. Ensure you have the Flare Hardhat Starter Kit set up.
  2. Update the VAULT_ADDRESS constant with the correct vault address for your network.
  3. Adjust the DEPOSIT_AMOUNT constant to the desired number of tokens.
  4. Ensure your account has sufficient asset balance (e.g., FXRP) to cover the deposit.
  5. Run the script using Hardhat:
npx hardhat run scripts/upshift/deposit.ts --network coston2

Output

The script outputs the following information about the deposit:

DEPOSIT TO VAULT

Vault Address: 0x24c1a47cD5e8473b64EAB2a94515a196E10C7C81
User Address: 0x0d09ff7630588E05E2449aBD3dDD1D8d146bc5c2

Reference Asset (asset depositing): 0x0b6A3645c240605887a5532109323A3E12273dc7

Deposit Amount: 1 FTestXRP (1000000)
Balance: 100.0 FTestXRP
Current Allowance: 0.0 FTestXRP

Approving vault to spend 1 FTestXRP tokens
Approval Tx: 0x87a36c1009575719fd3adb9a1bb2e3062a601bf910fc7fac3248da71891c39a4

Expected Shares: 0.99
Amount in Reference Tokens: 1.0
LP Balance Before: 0.0

Deposit: (tx: 0x446b7a171859d676677fc870cff81c7e8c0d618fc3588e60665792da86b94c50 , block: 12345678 )

Verifying deposit...
LP Balance After: 0.99
Shares Received: 0.99

Summary

In this guide, you learned how to deposit assets into an Upshift vault by specifying the amount of assets to deposit and receiving LP tokens in return.

What's next

To continue your Upshift development journey, you can: