# Claim Redemption from Upshift Vault

> Learn how to claim assets from a previously requested Upshift vault redemption

> 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/claim

This guide demonstrates how to claim assets from a previously requested redemption in 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.

Claiming is the final step after you have [requested a redemption](/fxrp/upshift/request-redeem). Once the lag duration has passed, you call [`claim()`](https://docs.upshift.finance/developer-docs/vault-contract-interface#id-3.-claim-uint256-year-uint256-month-uint256-day-address-receiveraddr) to receive your underlying assets (e.g., FXRP) in your wallet.

## 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)
-   A pending redemption request from a previous [request redeem](/fxrp/upshift/request-redeem) call.

## Upshift Vault Claim Script[​](#upshift-vault-claim-script "Direct link to Upshift Vault Claim Script")

The following script demonstrates how to claim assets from the Upshift vault:

scripts/upshift/claim.ts

```
/** * Upshift Tokenized Vault Claim Script * * This script claims assets from a previously requested redemption. * Use requestRedeem.ts first to schedule a redemption. * */import { web3 } from "hardhat";import { 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 RECEIVER_ADDRESS = ""; // Leave empty to use sender's address// Update these with the date from your requestRedeem callconst YEAR = 2026;const MONTH = 1;const DAY = 23;const ITokenizedVault = artifacts.require("ITokenizedVault");const IERC20 = artifacts.require("IERC20");const IERC20Metadata = artifacts.require("IERC20Metadata");const IFAsset = artifacts.require("IFAsset");async function getReferenceAssetInfo(vault: ITokenizedVaultInstance) {  const referenceAsset = await vault.asset();  const refAsset = await IFAsset.at(referenceAsset);  const refDecimals = Number(await refAsset.decimals());  const refSymbol = await refAsset.symbol();  return { referenceAsset, refAsset, refDecimals, refSymbol };}async function checkPendingRedemption(  vault: ITokenizedVaultInstance,  year: number,  month: number,  day: number,  receiverAddr: string,) {  console.log("\n1. Checking pending redemption...");  const shares = await vault.getBurnableAmountByReceiver(    year,    month,    day,    receiverAddr,  );  if (BigInt(shares.toString()) === 0n) {    console.log("No shares found for this date and receiver address");    return null;  }  return shares;}async function getLPTokenInfo(vault: ITokenizedVaultInstance) {  const lpTokenAddress = await vault.lpTokenAddress();  const lpToken = await IERC20Metadata.at(lpTokenAddress);  const lpDecimals = Number(await lpToken.decimals());  const lpSymbol = await lpToken.symbol();  return { lpTokenAddress, lpDecimals, lpSymbol };}async function previewRedemption(  vault: ITokenizedVaultInstance,  shares: { toString(): string },  refDecimals: number,  refSymbol: string,) {  console.log("\n2. Previewing redemption...");  const preview = await vault.previewRedemption(shares.toString(), false);  const assetsAmount = preview[0];  const assetsAfterFee = preview[1];  console.log(    `Assets (before fee): ${formatUnits(assetsAmount.toString(), refDecimals)} ${refSymbol}`,  );  console.log(    `Assets (after fee): ${formatUnits(assetsAfterFee.toString(), refDecimals)} ${refSymbol}`,  );  const fee =    BigInt(assetsAmount.toString()) - BigInt(assetsAfterFee.toString());  console.log(`Fee: ${formatUnits(fee.toString(), refDecimals)} ${refSymbol}`);  return { assetsAmount, assetsAfterFee };}async function checkIfClaimable(year: number, month: number, day: number) {  console.log("\n3. Checking if claimable...");  const block = await web3.eth.getBlock("latest");  const blockTimestamp = BigInt(block.timestamp);  const claimableDate = new Date(Date.UTC(year, month - 1, day, 0, 0, 0));  const claimableEpoch = BigInt(Math.floor(claimableDate.getTime() / 1000));  const TIMESTAMP_MANIPULATION_WINDOW = 300n; // 5 minutes  console.log(`Current Timestamp: ${blockTimestamp.toString()}`);  console.log(`Claimable Epoch: ${claimableEpoch.toString()}`);  const canClaim =    blockTimestamp + TIMESTAMP_MANIPULATION_WINDOW >= claimableEpoch;  if (!canClaim) {    const timeUntil =      claimableEpoch - blockTimestamp - TIMESTAMP_MANIPULATION_WINDOW;    const hoursUntil = Number(timeUntil) / 3600;    console.log("Cannot claim yet!");    console.log(`Wait approximately ${hoursUntil.toFixed(2)} more hours`);    console.log(      `Claimable after: ${new Date(Number(claimableEpoch) * 1000).toISOString()}`,    );    return false;  }  console.log("Ready to claim!");  return true;}async function getBalanceBefore(  referenceAsset: string,  receiverAddr: string,  refDecimals: number,  refSymbol: string,) {  console.log("\n4. Checking receiver balance before...");  const refToken: IERC20Instance = await IERC20.at(referenceAsset);  const balanceBefore = await refToken.balanceOf(receiverAddr);  console.log(    `Balance: ${formatUnits(balanceBefore.toString(), refDecimals)} ${refSymbol}`,  );  return { refToken, balanceBefore };}async function executeClaim(  vault: ITokenizedVaultInstance,  year: number,  month: number,  day: number,  receiverAddr: string,) {  console.log("\n5. Claiming...");  const claimTx = await vault.claim(year, month, day, receiverAddr);  console.log(    "Claim: (tx:",    claimTx.tx,    ", block:",    claimTx.receipt.blockNumber,    ")",  );}async function verifyClaim(  refToken: IERC20Instance,  receiverAddr: string,  balanceBefore: { toString(): string },  assetsAfterFee: { toString(): string },  refDecimals: number,  refSymbol: string,) {  console.log("\n6. Verifying claim...");  const balanceAfter = await refToken.balanceOf(receiverAddr);  const received =    BigInt(balanceAfter.toString()) - BigInt(balanceBefore.toString());  console.log(    `Balance After: ${formatUnits(balanceAfter.toString(), refDecimals)} ${refSymbol}`,  );  console.log(    `Received: ${formatUnits(received.toString(), refDecimals)} ${refSymbol}`,  );  if (received === BigInt(assetsAfterFee.toString())) {    console.log("Claim successful!");  } else {    console.log(      "Received amount differs from expected (may be due to rounding)",    );  }}async function main() {  // 1. Initialize: Get user account from Hardhat network  const accounts = await web3.eth.getAccounts();  const userAddress = accounts[0];  const receiverAddr = RECEIVER_ADDRESS || userAddress;  console.log("CLAIM REDEMPTION\n");  console.log("Vault Address:", VAULT_ADDRESS);  console.log("User Address:", userAddress);  console.log("Receiver Address:", receiverAddr);  console.log(    `Redemption Date: ${YEAR}-${String(MONTH).padStart(2, "0")}-${String(DAY).padStart(2, "0")}`,  );  // 2. Connect to the vault contract instance  const vault: ITokenizedVaultInstance =    await ITokenizedVault.at(VAULT_ADDRESS);  // 3. Get reference asset info  const { referenceAsset, refDecimals, refSymbol } =    await getReferenceAssetInfo(vault);  // 4. Check pending redemption  const shares = await checkPendingRedemption(    vault,    YEAR,    MONTH,    DAY,    receiverAddr,  );  if (!shares) return;  // 5. Get LP token info  const { lpTokenAddress, lpDecimals, lpSymbol } = await getLPTokenInfo(vault);  console.log(    `Shares to claim: ${formatUnits(shares.toString(), lpDecimals)} ${lpSymbol}`,  );  console.log(`LP Token Address: ${lpTokenAddress}`);  // 6. Preview redemption  const { assetsAfterFee } = await previewRedemption(    vault,    shares,    refDecimals,    refSymbol,  );  // 7. Check if claimable  const canClaim = await checkIfClaimable(YEAR, MONTH, DAY);  if (!canClaim) return;  // 8. Get balance before  const { refToken, balanceBefore } = await getBalanceBefore(    referenceAsset,    receiverAddr,    refDecimals,    refSymbol,  );  // 9. Execute claim  await executeClaim(vault, YEAR, MONTH, DAY, receiverAddr);  // 10. Verify claim  await verifyClaim(    refToken,    receiverAddr,    balanceBefore,    assetsAfterFee,    refDecimals,    refSymbol,  );}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, user, receiver addresses, and redemption date.
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.  **Check pending redemption:** Verifies that there are shares to claim for the given date and receiver.
5.  **Get LP token info:** Retrieves the LP token address, decimals, and symbol.
6.  **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.
7.  **Check if claimable:** Ensures the current block timestamp is past the claimable date (plus a small buffer) before proceeding.
8.  **Get balance before:** Records the receiver's asset balance before the claim.
9.  **Execute claim:** Calls [`claim()`](https://docs.upshift.finance/developer-docs/vault-contract-interface?q=getBurnableAmountByReceiver#id-3.-claim-uint256-year-uint256-month-uint256-day-address-receiveraddr) with the redemption date and receiver to transfer assets.
10.  **Verify claim:** Confirms the claim by comparing the receiver's new asset balance to the expected amount.

## Understanding the Claim Process[​](#understanding-the-claim-process "Direct link to Understanding the Claim Process")

The claim step completes the requested redemption flow:

1.  **Request:** You previously called [`requestRedeem()`](/fxrp/upshift/request-redeem) to lock LP tokens and create a withdrawal request for a specific epoch.
2.  **Wait:** The lag duration must pass before assets can be claimed.
3.  **Claim:** Once the claimable date has been reached, call `claim(year, month, day, receiver)` to receive your assets.

The script uses the **redemption date** (year, month, day) that was output when you ran the request redeem script. You must set `YEAR`, `MONTH`, and `DAY` in the script to match that date.

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

To run the Upshift vault claim 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.  Set `YEAR`, `MONTH`, and `DAY` to the claimable date from your [request redeem](/fxrp/upshift/request-redeem) output.
4.  Optionally set `RECEIVER_ADDRESS` to claim to a different address (leave empty to use the signer).
5.  Ensure the claimable date has passed (the script checks and exits with a message if not).
6.  Run the script using Hardhat:

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

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

The script outputs the following information about the claim:

```
CLAIM REDEMPTIONVault Address: 0x24c1a47cD5e8473b64EAB2a94515a196E10C7C81User Address: 0x0d09ff7630588E05E2449aBD3dDD1D8d146bc5c2Receiver Address: 0x0d09ff7630588E05E2449aBD3dDD1D8d146bc5c2Redemption Date: 2026-01-231. Checking pending redemption...2. Previewing redemption...Assets (before fee): 1.0 FTestXRPAssets (after fee): 0.995 FTestXRPFee: 0.005 FTestXRPShares to claim: 1.0LP Token Address: 0x...3. Checking if claimable...Current Timestamp: 1737648000Claimable Epoch: 1737586800Ready to claim!4. Checking receiver balance before...Balance: 50.0 FTestXRP5. Claiming...Claim: (tx: 0x3f1bd8c766852d3b835bcde79f6d8e20afeeb227d737e0ed28d057dc0e6b2ba9 , block: 12345678 )6. Verifying claim...Balance After: 50.995 FTestXRPReceived: 0.995 FTestXRPClaim successful!
```

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

In this guide, you learned how to claim assets from an Upshift vault after a requested redemption. You use the redemption date (year, month, day) from your request redeem output, and once the lag period has passed, the claim script transfers the underlying assets to your wallet.

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 [request a redemption](/fxrp/upshift/request-redeem) from an Upshift vault.
-   Learn how to [instantly redeem](/fxrp/upshift/instant-redeem) from an Upshift vault for immediate liquidity.
-   Learn how to [deposit assets](/fxrp/upshift/deposit) into an Upshift vault.
-   Learn more about [FAssets](/fassets/overview) and how the system works.
