Introduction
FWA Security Review
This is the security review of FWA (token-works/fwa-relaunch), a randomized NFT acquisition pool built on Chainlink VRF v2.5 and Uniswap v4. Each finding below has its own page with a reproducible proof of concept.
What FWA is
FWA is a randomized NFT acquisition pool with depositor-funded standing bids. A depositor lists an ERC721 together with a chosen amount of ETH backing. That backing does two things:
- It sets the listing's selection weight inversely (weight is
NUM / backing), so a lightly-backed listing is selected more often and a richly-backed one less often. - It funds an irrevocable standing bid from the depositor to reacquire the NFT.
A purchaser pays an expected-value-priced acquisition fee for a Chainlink VRF draw that allocates one randomly selected listing in proportion to its weight. The purchaser then either keeps the NFT or accepts the depositor's standing bid, selling the NFT back to its depositor for the escrowed ETH. The two outcomes are mutually exclusive: a purchaser can never retain both the NFT and the ETH.
Economic design
- Each listing's backing ETH is escrowed per listing and only ever settles that listing's standing bid, so the contract is always solvent and any un-allocated listing is fully withdrawable by its depositor.
- Acquisitions are priced at the pool's expected value times a protocol surcharge:
EV = Σ(weightᵢ·backingᵢ) / Σweightᵢ. With inverse weights this reduces to the harmonic mean of the backings, so a pool of richer listings prices cheaper, since an acquisition is far more likely to land a lightly-backed one. - Acquisition fees are shared among depositors equally per active listing via a dividend accumulator, keeping acquisitions cheap and small deposits attractive.
- A separate, marketable top-backed listing earns a share off every acquisition into a visible, growing pot, compounding the incentive for the highest-committed backers.
- Selection runs in
O(log n)via a sparse segment tree over active listing slots. - The system uses Chainlink VRF v2.5 (subscription, native payment): an owner-managed subscription pays the fulfillment gas, and each purchaser pays a
vrfServiceFeeout ofmsg.valueintended to self-fund the subscription.
Companion contracts round out the system: FWAToken (a transfer-locked incentive ERC20 that launches and buys back an ETH/FWAToken Uniswap v4 pool), FWATokenHook (the v4 hook that gates the pool and charges a flat fee), FWAClaim (Merkle distribution of the incentive token), and FWAWhitelist (deposit-collection allowlist manager).
Scope
| Item | Value |
|---|---|
| Repository | token-works/fwa-relaunch |
| Commit | 1085bf6 |
| Core contract | FWA.sol (~2,756 LoC) |
| Toolchain | Foundry · Solidity 0.8.26 · via_ir |
| Randomness | Chainlink VRF v2.5 subscription (native payment) |
Summary of findings
We investigated two findings in depth, each reproduced by a Foundry proof of concept.
| Finding | Severity | Summary |
|---|---|---|
| VRF selection steering | High | Ungated cancelStagedListing lets an attacker who has seen the VRF word steer the "random" selection onto a specific high-backed listing and drain 85% of its backing for a tiny fee. |
| VRF subscription fail-open | Medium | The VRF fee is priced at request time while the coordinator charges at fulfillment, draining the self-funding subscription; the "fail-closed" guarantee is false, so acquisitions strand and purchasers forfeit their non-refundable VRF fee. |
| Severity | Count | Focus |
|---|---|---|
| High | 1 | Break of the unbiased-selection invariant the acquisition mechanic rests on. |
| Medium | 1 | VRF self-funding economics and a false safety assumption (protocol-liveness risk). |
The high-severity steering bug undermines the fairness guarantee the entire acquisition mechanism depends on and should be fixed before launch. The medium-severity VRF economics flaw is an operational-liveness risk that also invalidates a documented safety assumption. A broader review of FWA.sol and its companion contracts produced further lower-severity findings, tracked outside this report.