Skip to content

Commit 3308ec4

Browse files
authored
feat(docs): fassets swap redeem guide (#681)
1 parent 7a7be34 commit 3308ec4

File tree

6 files changed

+431
-4
lines changed

6 files changed

+431
-4
lines changed

docs/fassets/developer-guides/3-fassets-redeem.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ sidebar_position: 3
1010
import CodeBlock from "@theme/CodeBlock";
1111
import Remix from "@site/src/components/remix";
1212
import FAssetsRedeem from "!!raw-loader!/examples/developer-hub-solidity/FAssetsRedeem.sol";
13+
import RedemptionProcessPrerequisites from "./_redemption_process_prerequisites.mdx";
1314

1415
## Overview
1516

1617
In this guide, you will learn how to redeem FAssets using the Asset Manager smart contract.
17-
Redemption is the process of burning FAssets (e.g., FXRP) on Flare in exchange for their equivalent value on the original chain (e.g., XRP on XRPL).
1818

19-
See the [Redemption](/fassets/redemption) overview for more details.
19+
<RedemptionProcessPrerequisites />
2020

2121
## Prerequisites
2222

@@ -48,7 +48,7 @@ In this example, you are not using the executor vault address, but you can use i
4848

4949
To deploy the contract and redeem FAssets, you can use the [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit).
5050

51-
Create a new file, for example `scripts/fassets/redeem.ts` and add the following code:
51+
Create a new file, for example, `scripts/fassets/redeem.ts` and add the following code:
5252

5353
### Import the Required Contracts
5454

@@ -141,7 +141,7 @@ In a production environment, you should use a more secure method to transfer FXR
141141
During the redemption process, the `AssetManager` emits an events:
142142

143143
- [`RedemptionRequested`](/fassets/reference/IAssetManagerEvents#redemptionrequested) - holds the agent vault address, redemption request id, the amount of FAssets to redeem, and other important information.
144-
- [`RedemptionTicketCreated`](/fassets/reference/IAssetManagerEvents#redemptionticketcreated) - holds the redemption ticket information that is updated during the redemption process.
144+
- [`RedemptionTicketCreated`](/fassets/reference/IAssetManagerEvents#redemptionticketcreated) - holds the redemption ticket information updated during the redemption process.
145145

146146
To parse the redemption events, you can use the following function:
147147

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
title: Swap and Redeem FAssets
3+
tags: [intermediate, fassets]
4+
slug: fassets-swap-redeem
5+
description: Learn how to swap and redeem FAssets
6+
keywords: [fassets, flare-network]
7+
sidebar_position: 4
8+
---
9+
10+
import CodeBlock from "@theme/CodeBlock";
11+
import Remix from "@site/src/components/remix";
12+
import FAssetsSwapAndRedeemContract from "!!raw-loader!/examples/developer-hub-solidity/FAssetsSwapAndRedeem.sol";
13+
import FAssetsSwapAndRedeemScript from "!!raw-loader!/examples/developer-hub-javascript/fassetsSwapAndRedeem.ts";
14+
import RedemptionProcessPrerequisites from "./_redemption_process_prerequisites.mdx";
15+
16+
## Overview
17+
18+
In this guide, you will learn how to swap a token (in this example, WCFLR) for FXRP and redeem FXRP for FAssets using the Uniswap V2 router (in this example, BlazeSwap) and the FAssets asset manager.
19+
20+
<RedemptionProcessPrerequisites />
21+
22+
## Swap and Redeem Smart Contract
23+
24+
The following Solidity contract demonstrates how to swap WCFLR for FXRP and then redeem FXRP to receive XRP on the XRPL.
25+
26+
### Contract Code
27+
28+
<CodeBlock language="solidity" title="contracts/fassets/SwapAndRedeem.sol">
29+
{FAssetsSwapAndRedeemContract}
30+
</CodeBlock>
31+
32+
This contract has two main functions:
33+
34+
- Swaps WCFLR for FXRP using a BlazeSwap router (Uniswap V2 compatible).
35+
- Redeems FAssets (FXRP) to an XRPL address using the FAssets asset manager.
36+
37+
### 1. Required Imports
38+
39+
The contract uses the following dependencies:
40+
41+
- `IERC20` OpenZeppelin standard ERC-20 interface.
42+
- `IAssetManager` interface to the FAssets Asset Manager.
43+
- `AssetManagerSettings` is used to retrieve lot size and configuration.
44+
45+
### 2. Interfaces
46+
47+
The `ISwapRouter` interface allows interaction with a Uniswap V2-compatible router:
48+
49+
- `swapExactTokensForTokens`: Swaps an exact amount of input tokens.
50+
- `getAmountsIn`: Calculates how much input is needed for a given output.
51+
52+
### 3. State Variables and Constructor
53+
54+
Defined state variables:
55+
56+
- `router`: Uniswap V2 router contract; in this example, it is the BlazeSwap router.
57+
- `assetManager`: Asset Manager handling FXRP redemption.
58+
- `token`: Token to swap (WCFLR in the swap path).
59+
- `swapPath`: Array of addresses defining the swap route (e.g., WCFLR → FXRP).
60+
61+
To instantiate the contract, the constructor sets up the Uniswap router, FAssets asset manager, and swap path.
62+
It initializes the token as the first token in the swap path.
63+
64+
### 4. Main Function: `swapAndRedeem`
65+
66+
The `swapAndRedeem` is the core function that executes the swap and redemption flow.
67+
68+
- **1. Validation**
69+
70+
- Ensure the caller has sufficient WCFLR balance.
71+
- Confirm the contract has enough FXRP allowance for redemption.
72+
73+
- **2. Transfer**
74+
75+
- Move WCFLR from the caller to the contract.
76+
- Approve the router to spend WCFLR on behalf of the contract.
77+
78+
- **3. Swap**
79+
80+
- Perform the swap from WCFLR to FXRP using the specified swap path.
81+
- Apply a 10-minute deadline for the swap operation.
82+
83+
- **4. Redemption**
84+
85+
- Redeem the obtained FXRP through the FAssets system.
86+
- Transfer the resulting XRP to the caller's XRPL address.
87+
88+
- **5. Helper Function: `calculateRedemptionAmountIn`**
89+
- Accept the number of FXRP lots intended for redemption.
90+
- Fetch the lot size from the FAssets asset manager and calculate the WCFLR needed for swap and redemption.
91+
92+
## Execute the Swap and Redeem
93+
94+
To execute the swap and redeem process, you need to deploy the smart contract instance and call the `swapAndRedeem` function.
95+
96+
<CodeBlock language="typescript" title="scripts/fassets/swapAndRedeem.ts">
97+
{FAssetsSwapAndRedeemScript}
98+
</CodeBlock>
99+
100+
### Code Breakdown
101+
102+
- **1. Dependencies and Constants**
103+
104+
- `ASSET_MANAGER_ADDRESS`: The address of the FAssets Asset Manager contract.
105+
- `LOTS_TO_REDEEM`: The number of FAsset lots to redeem (typically set to 1).
106+
- `UNDERLYING_ADDRESS`: The XRPL address that will receive the redeemed assets.
107+
- `SWAP_ROUTER_ADDRESS`: The address of the Uniswap V2-compatible swap router.
108+
- `SWAP_PATH`: An array of token addresses defining the swap path from WCFLR to FXRP.
109+
110+
- **2. Deploy and Verify**
111+
112+
- Deploys the `SwapAndRedeem` contract and verifies it using [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit).
113+
114+
- **3. Calculate Redemption Amounts**
115+
116+
- Calls `calculateRedemptionAmountIn` to determine the required WCFLR amount.
117+
118+
- **4. Approve Tokens**
119+
120+
- Uses the ERC-20 `approve` method to allow the contract to spend WCFLR.
121+
:::warning
122+
In a production environment, you should use a secure method to approve spending the tokens.
123+
:::
124+
125+
- **5. Execute the Swap and Redemption**
126+
- Calls `swapAndRedeem` to complete the FAssets redemption process.
127+
128+
### Run the Script
129+
130+
To run the script, use the [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit) with the following command:
131+
132+
```bash
133+
npx hardhat run scripts/fassets/swapAndRedeem.ts --network coston
134+
```
135+
136+
The script outputs transaction details, including swap amounts and redemption results.
137+
138+
:::tip
139+
For an in-depth explanation of the FAssets redemption process, refer to the [FAssets Redeem Guide](/fassets/developer-guides/fassets-redeem).
140+
:::
141+
142+
## Conclusion
143+
144+
In this guide, you learned how to:
145+
146+
- swap WCFLR for FXRP using Uniswap V2 compatible router (in this example, BlazeSwap);
147+
- redeem FXRP to XRP on the XRP Ledger using FAssets asset manager.
148+
149+
The complete code is in the [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Redemption is the process of burning FAssets (e.g., FXRP) on Flare in exchange for their equivalent value on the original chain (e.g., XRP on XRPL).
2+
3+
See the [Redemption](/fassets/redemption) overview for more details.
4+
5+
## Prerequisites
6+
7+
- [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit)
8+
- [Flare Network Periphery Contracts](https://www.npmjs.com/package/@flarenetwork/flare-periphery-contracts)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// 1. Dependancies and constants
2+
import { run } from "hardhat";
3+
4+
import { SwapAndRedeemInstance } from "../../typechain-types";
5+
import { ERC20Instance } from "../../typechain-types/@openzeppelin/contracts/token/ERC20/ERC20";
6+
7+
// AssetManager address on Songbird Testnet Coston network
8+
const ASSET_MANAGER_ADDRESS = "0x56728e46908fB6FcC5BCD2cc0c0F9BB91C3e4D34";
9+
const LOTS_TO_REDEEM = 1;
10+
const UNDERLYING_ADDRESS = "rSHYuiEvsYsKR8uUHhBTuGP5zjRcGt4nm";
11+
// BlazeSwap router address on Songbird Testnet Coston network
12+
const SWAP_ROUTER_ADDRESS = "0xf0D01450C037DB2903CF5Ff638Dd1e2e6B0EEDF4";
13+
const SWAP_PATH = [
14+
"0x767b25A658E8FC8ab6eBbd52043495dB61b4ea91", // WCFLR
15+
"0x36be8f2e1CC3339Cf6702CEfA69626271C36E2fd", // FXRP
16+
];
17+
18+
// 2. Deploy and verify the `SwapAndRedeem` smart contract
19+
async function deployAndVerifyContract() {
20+
const SwapAndRedeem = artifacts.require("SwapAndRedeem");
21+
const args = [SWAP_ROUTER_ADDRESS, ASSET_MANAGER_ADDRESS, SWAP_PATH];
22+
const swapAndRedeem: SwapAndRedeemInstance = await SwapAndRedeem.new(...args);
23+
24+
const fassetsSwapAndRedeemAddress = await swapAndRedeem.address;
25+
26+
try {
27+
await run("verify:verify", {
28+
address: fassetsSwapAndRedeemAddress,
29+
constructorArguments: args,
30+
});
31+
} catch (e) {
32+
console.log(e);
33+
}
34+
35+
console.log("FAssetsSwapAndRedeem deployed to:", fassetsSwapAndRedeemAddress);
36+
37+
return swapAndRedeem;
38+
}
39+
40+
async function main() {
41+
// 2. Deploy and verify the `SwapAndRedeem` smart contract
42+
const swapAndRedeem: SwapAndRedeemInstance = await deployAndVerifyContract();
43+
44+
// 3. Calculate Required Amounts
45+
const swapAndRedeemAddress = await swapAndRedeem.address;
46+
const amounts =
47+
await swapAndRedeem.calculateRedemptionAmountIn(LOTS_TO_REDEEM);
48+
const amountIn = amounts.amountIn;
49+
const amountOut = amounts.amountOut;
50+
console.log("Amount of tokens out (FXRP): ", amountOut.toString());
51+
console.log("Amount of tokens in (WCFLR): ", amountIn.toString());
52+
53+
// 4. Approve spending WCFLR tokens
54+
const ERC20 = artifacts.require("ERC20");
55+
const wcflr: ERC20Instance = await ERC20.at(SWAP_PATH[0]);
56+
57+
const approveTx = await wcflr.approve(swapAndRedeemAddress, amountOut);
58+
console.log("Approve transaction: ", approveTx);
59+
60+
// 5. Swap WCFLR for FXRP and redeem to underlying XRP token on XRP Ledger
61+
const swapResult = await swapAndRedeemAddress.swapAndRedeem(
62+
LOTS_TO_REDEEM,
63+
UNDERLYING_ADDRESS,
64+
);
65+
console.log("Swap and redeem transaction: ", swapResult);
66+
}
67+
68+
main().catch((error) => {
69+
console.error(error);
70+
process.exitCode = 1;
71+
});

examples/developer-hub-solidity/FAssetsRedeem.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ contract FAssetsRedeem {
3333
uint256 redeemedAmountUBA = assetManager.redeem(
3434
_lots,
3535
_redeemerUnderlyingAddressString,
36+
// The account that is allowed to execute redemption default (besides redeemer and agent).
37+
// In this case it is not used
3638
payable(address(0))
3739
);
3840

0 commit comments

Comments
 (0)