# Request Redeem from Upshift Vault

> Learn how to request a delayed redemption from an Upshift vault

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

Source: https://dev.flare.network/fxrp/upshift/request-redeem

This guide demonstrates how to request a delayed redemption from an Upshift vault. The Upshift vault implements an [ERC-4626](https://eips.ethereum.org/EIPS/eip-4626) style tokenized vault that supports requested redemptions with a lower fee than instant redemptions.

Requesting a redemption locks your LP tokens (vault shares) and creates a withdrawal request. After the lag duration passes, you can claim your assets using the [claim redemption script](/fxrp/upshift/claim).

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

-   [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit)
-   [Flare Network Periphery Contracts](https://www.npmjs.com/package/@flarenetwork/flare-periphery-contracts)
-   Understanding of [FAssets](/fassets/overview)
-   LP tokens (vault shares) in the Upshift vault to redeem.

## Upshift Vault Request Redeem Script[​](#upshift-vault-request-redeem-script "Direct link to Upshift Vault Request Redeem Script")

The following script demonstrates how to request a delayed redemption from the Upshift vault:

scripts/upshift/requestRedeem.ts

```
/** * Upshift Tokenized Vault Request Redeem Script * * This script requests a delayed redemption of LP shares from the Upshift Tokenized Vault. * After the lag duration passes, use the claim script to receive assets. * */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 SHARES_TO_REDEEM = "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("Reference Asset (asset receiving):", referenceAsset);  return { referenceAsset, refAsset, decimals, symbol };}async function getLPTokenInfo(  vault: ITokenizedVaultInstance,  userAddress: string,  decimals: number,) {  const lpTokenAddress = await vault.lpTokenAddress();  const lpToken: IERC20Instance = await IERC20.at(lpTokenAddress);  const lpBalance = await lpToken.balanceOf(userAddress);  console.log(`\nLP Balance: ${formatUnits(lpBalance.toString(), decimals)}`);  return { lpToken, lpBalance };}function checkLPBalance(  lpBalance: { toString(): string },  sharesToRedeem: bigint,) {  if (BigInt(lpBalance.toString()) < sharesToRedeem) {    console.log("Insufficient LP balance!");    return false;  }  return true;}async function checkAndApproveLPAllowance(  lpToken: IERC20Instance,  userAddress: string,  sharesToRedeem: bigint,  decimals: number,) {  const lpAllowance = await lpToken.allowance(userAddress, VAULT_ADDRESS);  console.log(    `\nCurrent LP Allowance: ${formatUnits(lpAllowance.toString(), decimals)}`,  );  if (BigInt(lpAllowance.toString()) < sharesToRedeem) {    console.log(`\nApproving vault to spend ${SHARES_TO_REDEEM} LP tokens...`);    const approveTx = await lpToken.approve(      VAULT_ADDRESS,      sharesToRedeem.toString(),    );    console.log("Approval Tx:", approveTx.tx);  }}async function checkVaultConfiguration(  vault: ITokenizedVaultInstance,  sharesToRedeem: bigint,  decimals: number,  symbol: string,) {  const lagDuration = await vault.lagDuration();  const withdrawalFee = await vault.withdrawalFee();  const withdrawalsPaused = await vault.withdrawalsPaused();  const maxWithdrawalAmount = await vault.maxWithdrawalAmount();  console.log(`\nLag Duration: ${lagDuration.toString()} seconds`);  console.log(`Withdrawal Fee: ${formatUnits(withdrawalFee.toString(), 16)}%`);  console.log(`Withdrawals Paused: ${withdrawalsPaused}`);  console.log(    `Max Withdrawal Amount: ${formatUnits(maxWithdrawalAmount.toString(), decimals)} ${symbol}`,  );  if (withdrawalsPaused) {    console.log("\nError: Withdrawals are currently paused!");    return false;  }  if (    BigInt(maxWithdrawalAmount.toString()) > 0n &&    sharesToRedeem > BigInt(maxWithdrawalAmount.toString())  ) {    console.log("\nError: Shares to redeem exceeds max withdrawal amount!");    return false;  }  return true;}async function previewRedemption(  vault: ITokenizedVaultInstance,  sharesToRedeem: bigint,  decimals: number,  symbol: string,) {  const preview = await vault.previewRedemption(    sharesToRedeem.toString(),    false,  );  const assetsAmount = preview[0];  const assetsAfterFee = preview[1];  console.log(    `\nExpected Assets (before fee): ${formatUnits(assetsAmount.toString(), decimals)} ${symbol}`,  );  console.log(    `Expected Assets (after fee): ${formatUnits(assetsAfterFee.toString(), decimals)} ${symbol}`,  );}async function printWithdrawalEpoch(vault: ITokenizedVaultInstance) {  const epochInfo = await vault.getWithdrawalEpoch();  console.log(    `\nCurrent Epoch - Year: ${epochInfo[0].toString()}, Month: ${epochInfo[1].toString()}, Day: ${epochInfo[2].toString()}`,  );  console.log(`Claimable Epoch: ${epochInfo[3].toString()}`);}async function executeRequestRedeem(  vault: ITokenizedVaultInstance,  sharesToRedeem: bigint,  userAddress: string,) {  const requestTx = await vault.requestRedeem(    sharesToRedeem.toString(),    userAddress,  );  console.log(    "\nRequest Redeem: (tx:",    requestTx.tx,    ", block:",    requestTx.receipt.blockNumber,    ")",  );}async function verifyRequest(  vault: ITokenizedVaultInstance,  lpToken: IERC20Instance,  userAddress: string,  lpBalanceBefore: { toString(): string },  decimals: number,) {  const lpBalanceAfter = await lpToken.balanceOf(userAddress);  const sharesLocked =    BigInt(lpBalanceBefore.toString()) - BigInt(lpBalanceAfter.toString());  console.log(    `LP Balance After: ${formatUnits(lpBalanceAfter.toString(), decimals)}`,  );  console.log(    `Shares Locked: ${formatUnits(sharesLocked.toString(), decimals)}`,  );  const newEpochInfo = await vault.getWithdrawalEpoch();  console.log(    `\nClaim your assets after: ${newEpochInfo[0].toString()}/${newEpochInfo[1].toString()}/${newEpochInfo[2].toString()}`,  );}async function main() {  // 1. Initialize: Get user account from Hardhat network  const accounts = await web3.eth.getAccounts();  const userAddress = accounts[0];  console.log("REQUEST REDEEM FROM 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 { decimals, symbol } = await getReferenceAssetInfo(vault);  // 4. Get LP token info  const { lpToken, lpBalance } = await getLPTokenInfo(    vault,    userAddress,    decimals,  );  // 5. Convert shares amount and validate balance  const sharesToRedeem = parseUnits(SHARES_TO_REDEEM, decimals);  console.log(    `Shares to Redeem: ${SHARES_TO_REDEEM} (${sharesToRedeem.toString()})`,  );  const hasBalance = checkLPBalance(lpBalance, sharesToRedeem);  if (!hasBalance) return;  // 6. Check and approve LP allowance  await checkAndApproveLPAllowance(    lpToken,    userAddress,    sharesToRedeem,    decimals,  );  // 7. Check vault configuration  const canProceed = await checkVaultConfiguration(    vault,    sharesToRedeem,    decimals,    symbol,  );  if (!canProceed) return;  // 8. Preview redemption  await previewRedemption(vault, sharesToRedeem, decimals, symbol);  // 9. Print withdrawal epoch info  await printWithdrawalEpoch(vault);  // 10. Execute request redeem  await executeRequestRedeem(vault, sharesToRedeem, userAddress);  // 11. Verify request  await verifyRequest(vault, lpToken, userAddress, lpBalance, decimals);}main().catch((error) => {  console.error(error);  process.exitCode = 1;});
```

## Script Breakdown[​](#script-breakdown "Direct link to 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.  **Get LP token info:** Retrieves the LP token address and the user's current LP balance.
5.  **Validate balance:** Converts the shares amount and checks if the user has sufficient LP tokens.
6.  **Approve LP allowance:** Approves the vault to spend LP tokens if the current allowance is insufficient.
7.  **Check vault configuration:** Verifies withdrawals are not paused and the amount doesn't exceed maximum limits.
8.  **Preview redemption:** Calls [`previewRedemption()`](https://docs.upshift.finance/developer-docs/vault-contract-interface#id-8.-previewredeem-uint256-shares) to see expected assets before and after the withdrawal fee.
9.  **Print withdrawal epoch:** Displays the current epoch and claimable epoch information.
10.  **Execute request redeem:** Calls [`requestRedeem()`](https://docs.upshift.finance/developer-docs/vault-contract-interface#id-2.-requestredeem-uint256-shares-address-receiveraddr-address-holderaddr) to lock LP tokens and create a withdrawal request.
11.  **Verify request:** Confirms the request by checking the updated LP balance and showing when assets can be claimed.

## Understanding Requested Redemption[​](#understanding-requested-redemption "Direct link to Understanding Requested Redemption")

The Upshift vault supports two types of redemptions:

-   **Instant Redemption**: Immediately burns LP tokens and returns assets, but incurs an instant redemption fee.
-   **Requested Redemption**: Creates a withdrawal request that is processed after a lag period, with a lower fee.

The requested redemption process works as follows:

1.  **Request**: Call [`requestRedeem()`](https://docs.upshift.finance/developer-docs/vault-contract-interface#id-2.-requestredeem-uint256-shares-address-receiveraddr-address-holderaddr) to lock your LP tokens and create a withdrawal request for the current epoch.
2.  **Wait**: The lag duration must pass before you can claim your assets.
3.  **Claim**: After the lag period execute the [claim redemption script](/fxrp/upshift/claim) to receive your assets.

This delayed mechanism allows the vault to manage liquidity more efficiently while offering users a lower fee option.

## Running the Script[​](#running-the-script "Direct link to Running the Script")

To run the Upshift vault request redeem script:

1.  Ensure you have the [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit) set up.
2.  Update the `VAULT_ADDRESS` constant with the correct vault address for your network.
3.  Adjust the `SHARES_TO_REDEEM` constant to the desired number of shares.
4.  Ensure your account has sufficient LP tokens (vault shares) to cover the redemption.
5.  Run the script using Hardhat:

```
yarn hardhat run scripts/upshift/requestRedeem.ts --network coston2
```

## Output[​](#output "Direct link to Output")

The script outputs the following information about the request redemption:

```
REQUEST REDEEM FROM VAULTVault Address: 0x24c1a47cD5e8473b64EAB2a94515a196E10C7C81User Address: 0x0d09ff7630588E05E2449aBD3dDD1D8d146bc5c2Reference Asset (asset receiving): 0x0b6A3645c240605887a5532109323A3E12273dc7LP Balance: 10.0Shares to Redeem: 1 (1000000)Current LP Allowance: 0.0Approving vault to spend 1 LP tokens...Approval Tx: 0x87a36c1009575719fd3adb9a1bb2e3062a601bf910fc7fac3248da71891c39a4Lag Duration: 86400 secondsWithdrawal Fee: 0.5%Withdrawals Paused: falseMax Withdrawal Amount: 1000000.0 FTestXRPExpected Assets (before fee): 1.0 FTestXRPExpected Assets (after fee): 0.995 FTestXRPCurrent Epoch - Year: 2025, Month: 1, Day: 15Claimable Epoch: 14Request Redeem: (tx: 0x3f1bd8c766852d3b835bcde79f6d8e20afeeb227d737e0ed28d057dc0e6b2ba9 , block: 12345678 )LP Balance After: 9.0Shares Locked: 1.0Claim your assets after: 2025/1/16
```

## Summary[​](#summary "Direct link to Summary")

In this guide, you learned how to request a delayed redemption from an Upshift vault by specifying the number of LP tokens (shares) to redeem. The requested redemption has a lower fee than instant redemption but requires waiting for the lag duration before claiming your assets.

What's next

To continue your Upshift development journey, you can:

-   Learn how to [get Upshift vault status](/fxrp/upshift/status) to monitor your redemption requests.
-   Learn how to [claim assets from an Upshift vault](/fxrp/upshift/claim) after your requested redemption is claimable.
-   Learn how to [instantly redeem from an Upshift vault](/fxrp/upshift/instant-redeem) for immediate liquidity.
-   Learn how to [deposit assets into an Upshift vault](/fxrp/upshift/deposit).
-   Learn more about [FAssets](/fassets/overview) and how the system works.
