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
- Flare Hardhat Starter Kit
- Flare Network Periphery Contracts
- Understanding of FAssets
- Sufficient asset balance (e.g., FXRP) to deposit into the vault.
Upshift Vault Deposit Script
The following script demonstrates how to deposit assets into the Upshift vault:
/**
* 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:
- Initialize: Gets the user account and logs the vault and user addresses.
- Connect to vault: Creates an instance of the Upshift vault contract.
- Get reference asset info: Retrieves the vault's reference asset (FXRP) address, symbol, and decimals.
- Calculate deposit amount: Converts the desired amount into the correct units based on decimals.
- Check balance: Verifies the user has sufficient balance to cover the deposit.
- Approve allowance: Approves the vault to spend the deposit amount if needed.
- Preview deposit: Calls
previewDeposit()to see the expected shares and amount in reference tokens. - Get LP token info: Records the LP token balance before the deposit.
- Execute deposit: Calls
deposit()to transfer assets and mint LP tokens. - 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:
- Ensure you have the Flare Hardhat Starter Kit set up.
- Update the
VAULT_ADDRESSconstant with the correct vault address for your network. - Adjust the
DEPOSIT_AMOUNTconstant to the desired number of tokens. - Ensure your account has sufficient asset balance (e.g., FXRP) to cover the deposit.
- 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.
To continue your Upshift development journey, you can:
- Learn more about FAssets and how the system works.
- Learn how to get Upshift vault status to monitor your position.
- Learn how to instantly redeem from an Upshift vault for immediate liquidity.
- Learn how to request a redemption from an Upshift vault for delayed liquidity.
- Learn how to claim assets from an Upshift vault after your requested redemption is claimable.