#47082 [SC-Low] Zero collateral payout despite burned fAssets
Submitted on Jun 8th 2025 at 19:25:48 UTC by @dldLambda for Audit Comp | Flare | FAssets
Report ID: #47082
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/flare-foundation/fassets/blob/main/contracts/assetManager/library/RedemptionRequests.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
There is a vulnerability in the collateral redemption logic where the conversion of AMG (a unit representing fractional assets) to token wei (native token units) suffers from precision loss due to scaling and rounding. As a result, under certain conditions, redeemers burn their fAssets but receive zero collateral payout. This issue can lead to users losing expected payouts, undermining trust and usability.
Vulnerability Details
Vulnerability manifests itself in function "redeemFromAgentInCollateral".
Call chain:
redeemFromAgentInCollateral (RedemptionRequestsFacet.sol) ---> RedemptionRequests.redeemFromAgentInCollateral
What happens in the logic:
The user (redeemer) owns some fAssets — tokens that represent a share in the collateral pool.
The user calls the fAssets redemption function to burn their fAssets and get back the collateral — a native token (e.g. USDC, FLR, etc.).
The payout amount is calculated using the AMG price (the conventional unit associated with fAssets) in units of the collateral token (tokenWei).
The AMG price is taken from the oracle (FTSO), then multiplied by the amount of AMG being burned and divided by the scaling factor to get the amount of tokens to be paid out.
However, under certain conditions, the function "convertAmgToTokenWei" can round the value to zero, which leads to a zero payout when burning the user's fassets:
For this, a very low value of "_amgToTokenWeiPrice" is required - which is possible with specific tokens or/and a reduced price of AMG (and this does not depend on the decimals) - which is theoretically possible, since when obtaining this value, an FTSO oracle is used, which, like any other, can be subject to fluctuations due to high volatility:
(It is noteworthy that this situation is possible even if function "calcAmgToTokenWeiPrice" returns a normal value)
If _valueAMG*_amgToTokenWeiPrice < AMG_TOKEN_WEI_PRICE_SCALE - rounding down to zero occurs and the user receives nothing, but his fassets tokens are still burned.
This situation is possible, since the value of variable "_amgToTokenWeiPrice" depends on the price received from the oracle - and is possible even with other normally detailed parameters. This market price may be temporary - however, users irrevocably lose their funds.
Impact Details
Users redeeming fAssets can receive zero payout, losing their expected collateral returns.
This loss is due to rounding and not due to protocol insolvency or direct theft.
The protocol retains collateral; funds are not stolen or lost, but payouts are unfairly zeroed out.
This may erode user trust and negatively impact protocol usability.
Exploiting this requires an external condition (AMG price dropping significantly) which depends on oracle data and market dynamics.
The bug does not cause loss of collateral but violates promised returns.
References
https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/contracts/assetManager/library/RedemptionRequests.sol#L97 - function redeemFromAgentInCollateral
https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/contracts/assetManager/library/Conversion.sol#L182 - function convertAmgToTokenWei
https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/contracts/assetManager/library/Conversion.sol#L162 - function calcAmgToTokenWeiPrice
https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/contracts/assetManager/library/Conversion.sol#L128 - function currentAmgPriceInTokenWeiWithTs
Proof of Concept
Proof of Concept
change value 1000000000000 ---> 1000000000 (I tested it on smaller value) (https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/test/unit/fasset/library/Redemption.ts#L167)
add this import (import "hardhat/console.sol";) in RedemptionRequests.sol (https://github.com/flare-foundation/fassets/blob/main/contracts/assetManager/library/RedemptionRequests.sol#L15) - to use console.log()
add a modifications to function redeemFromAgentInCollateral (https://github.com/flare-foundation/fassets/blob/fc727ee70a6d36a3d8dec81892d76d01bb22e7f1/contracts/assetManager/library/RedemptionRequests.sol#L97)
//modify1-2,5-7 to clearly see all the values in the logs
//modify2-3 - to simulate significant change in price
Add into test/unit/fasset/library/Redemption.ts and run this test with the command (yarn testHH --grep "dl_dLambda_test3"):
And you will see the following output in the logs:
closedAMG - is how much will be burned. paymentWei - is how much will be paid to the user.
Was this helpful?