#47010 [SC-Low] `CollateralPool::donateNat` manipulation enables arbitrary pool‐token value inflation and fee‐debt evasion
Submitted on Jun 7th 2025 at 20:17:14 UTC by @NHristov for Audit Comp | Flare | FAssets
Report ID: #47010
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/flare-foundation/fassets/blob/main/contracts/assetManager/implementation/CollateralPool.sol
Impacts:
Theft of unclaimed yield
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Description
Brief/Intro
In CollateralPool::enter, new pool‐tokens are minted in proportion to
tokenShare ≃ poolTokenSupply × (depositNat / poolNatBalance)Yet CollateralPool::donateNat lets anyone add up to ≈1% of the current poolNatBalance without minting tokens. By repeatedly donating just under that 1% cap, an attacker can inflate poolNatBalance while leaving poolTokenSupply fixed, so that
1 poolToken → poolNatBalance / poolTokenSupplygrows arbitrarily large. A single token can end up “worth” millions of NAT, breaking the economic invariants of the pool.
Vulnerability Details
The core of the issue is that CollateralPool::donateNat does not mint any pool tokens while new pool tokens are minted in CollateralPool::enter in proportion to the amount of NAT deposited, but the pool's NAT balance can be inflated without minting any new tokens. This means that the value of a single pool token can be manipulated by repeatedly donating just under the 1% cap.
For example attack can be executes as follows based on the ratio depositNat / poolNatBalance.
By repeatedly calling donateNat() with up to ~1% of the current
poolNatBalance, an attacker can inflate poolNatBalance without increasing poolTokenSupply. Each donation multiplies the collateral base by ~1.01×, and after N donations:
so that
grows exponentially. Once the ratio is enormous, an attacker can:
Exit 99% of their tokens (leaving ≥1 token) via
exit(tokens * 99/100)and burns nearly all tokens, reducing poolTokenSupply to ~1–2, but leavestotalCollateralhuge.Redeem fees for “free”:
After the manipulation loop, fAssetFeeDebtOf(attacker)==0, so calling enter(0, true) with a tiny deposit mints collateral-pool tokens at the inflated ratio, evading any owed f-asset fees.
That final 1 token now represents millions of NAT, which can never be withdrawn (exit requires ≥1 token after exit), locking enormous funds.
Impact Details
The last locked token in the pool can be worth millions of NAT, which can never be withdrawn.
The attacker can redeem fees for “free” by entering the pool with a tiny deposit after inflating the pool's NAT balance.
The economic invariants of the pool are broken, allowing for manipulation of the value of pool tokens.
References
Proof of Concept
Proof Of Concept
The following unit test demonstrates the exploit:
To run the test paste the code in the CollateralPool.ts unit test file and execute it
Was this helpful?