Mint Firelight Vault Shares
Overview
This guide demonstrates how to mint vault shares in a Firelight vault by depositing assets. The Firelight vault implements the ERC-4626 standard, which allows users to deposit assets (e.g., FXRP) and receive vault shares in return.
Minting shares is the process of depositing assets into the vault and receiving vault shares, which 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.
Firelight Vault Mint Script
The following script demonstrates how to mint vault shares by depositing assets into the Firelight vault:
/**
* FirelightVault Mint Script
*
* This script mints vault shares (ERC-4626) by depositing assets into the FirelightVault.
* It checks max mint capacity, calculates required assets, approves tokens, and mints shares.
*/
import { ethers } from "hardhat";
import { bnToBigInt } from "../utils/core";
import type { IFirelightVaultInstance } from "../../typechain-types/contracts/firelight/IFirelightVault";
import type { ERC20Instance } from "../../typechain-types/@openzeppelin/contracts/token/ERC20/ERC20";
export const FIRELIGHT_VAULT_ADDRESS =
"0x91Bfe6A68aB035DFebb6A770FFfB748C03C0E40B";
const sharesToMint = 1; // Number of shares to mint
// @ts-expect-error - Type definitions issue, but works at runtime
const IERC20 = artifacts.require(
"@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20",
);
const FirelightVault = artifacts.require("IFirelightVault");
async function getAccount() {
const [signer] = await ethers.getSigners();
return { signer, account: signer.address };
}
async function getVaultAndAsset() {
const vault = (await FirelightVault.at(
FIRELIGHT_VAULT_ADDRESS,
)) as IFirelightVaultInstance;
const assetAddress = await vault.asset();
const assetToken = (await IERC20.at(assetAddress)) as ERC20Instance;
return { vault, assetAddress, assetToken };
}
async function getAssetInfo(assetToken: ERC20Instance) {
const symbol = await assetToken.symbol();
const assetDecimals = (await assetToken.decimals()).toNumber();
return { symbol, assetDecimals };
}
function logMintInfo(
account: string,
assetAddress: string,
symbol: string,
assetDecimals: number,
sharesAmount: bigint,
) {
console.log("=== Mint vault shares (ERC-4626) ===");
console.log("Sender:", account);
console.log("Vault:", FIRELIGHT_VAULT_ADDRESS);
console.log("Asset:", assetAddress, `(${symbol}, decimals=${assetDecimals})`);
console.log(
"Shares to mint:",
sharesAmount.toString(),
`(= ${sharesToMint} share${sharesToMint > 1 ? "s" : ""})`,
);
}
async function validateMint(
vault: IFirelightVaultInstance,
account: string,
sharesAmount: bigint,
) {
const maxMint = bnToBigInt(await vault.maxMint(account));
console.log("Max mint:", maxMint.toString());
if (sharesAmount > maxMint) {
console.error(
`Cannot mint ${sharesAmount.toString()} shares. Max allowed: ${maxMint.toString()}`,
);
process.exit(1);
}
}
async function calculateAssetsNeeded(
vault: IFirelightVaultInstance,
sharesAmount: bigint,
) {
const assetsNeeded = await vault.previewMint(sharesAmount.toString());
console.log("Assets needed (from previewMint):", assetsNeeded.toString());
return assetsNeeded;
}
async function approveTokens(
assetToken: ERC20Instance,
vault: IFirelightVaultInstance,
amount: bigint,
account: string,
) {
const approveTx = await assetToken.approve(vault.address, amount.toString(), {
from: account,
});
console.log("Approve tx:", approveTx.tx);
}
async function executeMint(
vault: IFirelightVaultInstance,
sharesAmount: bigint,
account: string,
) {
const mintTx = await vault.mint(sharesAmount.toString(), account, {
from: account,
});
console.log("Mint tx:", mintTx.tx);
}
async function main() {
// 1. Get the account
const { account } = await getAccount();
// 2. Get the vault and asset token
const { vault, assetAddress, assetToken } = await getVaultAndAsset();
// 3. Get asset info (symbol, decimals)
const { symbol, assetDecimals } = await getAssetInfo(assetToken);
// 4. Calculate the shares amount to mint
const sharesAmount = BigInt(sharesToMint * 10 ** assetDecimals);
// 5. Log mint info
logMintInfo(account, assetAddress, symbol, assetDecimals, sharesAmount);
// 6. Validate the mint (check max mint)
await validateMint(vault, account, sharesAmount);
// 7. Calculate assets needed using previewMint
const assetsNeeded = await calculateAssetsNeeded(vault, sharesAmount);
// 8. Approve tokens for transfer
await approveTokens(assetToken, vault, bnToBigInt(assetsNeeded), account);
// 9. Execute the mint
await executeMint(vault, sharesAmount, account);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Script Breakdown
The main() function executes the following steps:
- Get the account: Retrieves the signer account from the Hardhat environment.
- Get the vault and asset token: Connects to the vault contract and retrieves the underlying asset token.
- Get asset info: Fetches the asset token's symbol and decimals.
- Calculate the shares amount to mint: Converts the desired shares into the correct units based on decimals.
- Log mint info: Displays the mint details, including sender, vault, and shares.
- Validate the mint: Checks if the amount exceeds the maximum allowed.
- Calculate assets needed: Uses
previewMint()to determine the required assets. - Approve tokens for transfer: Approves the vault to spend the required assets.
- Execute the mint: Calls
mint()to transfer assets and mint shares.
Running the Script
To run the Firelight vault mint script:
- Ensure you have the Flare Hardhat Starter Kit set up.
- Update the
FIRELIGHT_VAULT_ADDRESSconstant with the correct vault address for your network. - Adjust the
SHARES_TO_MINTconstant to the desired number of shares. - Ensure your account has sufficient asset balance (e.g., FXRP) to cover the minting cost.
- Run the script using Hardhat:
npx hardhat run scripts/firelight/mint.ts --network coston2
Output
The script outputs the following information:
=== Mint vault shares (ERC-4626) ===
Sender: 0x0d09ff7630588E05E2449aBD3dDD1D8d146bc5c2
Vault: 0x91Bfe6A68aB035DFebb6A770FFfB748C03C0E40B
Asset: 0x0b6A3645c240605887a5532109323A3E12273dc7 (FTestXRP, decimals=6)
Shares to mint: 1000000 (= 1 share)
Max mint: 115792089237316195423570985008687907853269984665640564039457584007913129639935
Assets needed (from previewMint): 1000000
Approve tx: 0xfe5683b82a4997df7d7b7c22c8c4dc416cdec8d1380dceeb996279c64c525460
Mint tx: 0x14d1c7ffe4f3b6a9fa04315eb8592ff9c64f2ae80c7e6e3a6e1b9cf9478106c3
Difference Between Mint and Deposit
The Firelight vault provides two ways to add assets:
mint: You specify the number of shares you want, and the vault calculates how many assets you need to deposit.deposit: You specify the amount of assets to deposit, and the vault calculates how many shares you'll receive based on the current exchange rate.
Both functions follow the ERC-4626 standard and result in the same outcome: you deposit assets and receive vault shares.
Summary
In this guide, you learned how to mint vault shares in a Firelight vault by specifying the number of shares you want.
To continue your Firelight development journey, you can:
- Learn how to get Firelight vault status to monitor your position.
- Learn how to deposit assets into a Firelight vault by specifying the amount of assets to deposit.
- Learn how to withdraw assets from a Firelight vault.
- Learn how to redeem assets from a Firelight vault.
- Explore the FAssets system overview to understand the broader ecosystem.