Redemption insurance for FXRP β if your redemption agent never delivers XRP, Flare's own on-chain proof pays you make-whole
FAssets let XRP holders bring their asset into Flare DeFi β but the redemption leg (turning
FXRP back into native XRP) is the riskiest step. When you redeem, an assigned agent must send you
XRP by a deadline. If it doesn't, you have to notice the miss, commission a Flare Data Connector
proof yourself, call redemptionPaymentDefault(), and accept collateral compensation at a haircut.
It's manual, slow, and uncertain β and that uncertainty keeps desks and treasuries from redeeming at
size, quietly weakening confidence in the FXRP peg.
Backstop turns that into a one-click guarantee. You buy a guard bound to your on-chain
redemption ticket for a small FTSO-priced premium. An autonomous keeper watches the deadline. If
the agent doesn't pay, anyone can submit Flare's FDC ReferencedPaymentNonexistence attestation
β the exact proof the FAssets protocol itself accepts for a redemption default β and Backstop
verifies it on-chain and pays you make-whole instantly. Underwriters fund the pool and earn the
premiums of every guard whose agent paid on time.
Backstop doesn't re-invent cross-chain trust β it rides Flare's own default mechanism.
Six engine-class Flare methods, wired in code and proven on Coston2:
| # | Flare method | Role in Backstop |
|---|---|---|
| 1 | IFdcVerification.verifyReferencedPaymentNonexistence |
the claim gate β proves the agent did NOT pay |
| 2 | IFdcHub.requestAttestation (RPN) |
keeper requests the non-payment attestation |
| 3 | FDC DA-Layer proof fetch | retrieves the finalized proof + Merkle path |
| 4 | IAssetManager.redemptionRequestInfo |
binds a guard to a real FXRP redemption ticket |
| 5 | FtsoV2.getFeedById (XRP/USD, FLR/USD) |
sizes coverage + prices premium/payout |
| 6 | FlareContractRegistry.getContractAddressByName |
resolves everything β nothing hardcoded |
Take Flare out and you'd need four separate systems: a cross-chain XRPL light client, a decentralized "payment-did-not-happen" attestation network, a price oracle, and a canonical FXRP redemption registry. Backstop is ~550 lines of Solidity because Flare enshrines all four β and FDC's non-existence proof is something almost no other chain exposes natively.
flowchart TD
U[Redeemer] -->|redeem FXRP| AM[FAssets AssetManager]
U -->|buyGuard ticket + premium| BS[Backstop]
LP[Underwriters] -->|deposit / withdraw| POOL[BackstopPool]
BS <-->|lock exposure Β· payout| POOL
BS -->|getFeedById XRP/USD Β· FLR/USD| FTSO[FtsoV2]
BS -->|redemptionRequestInfo| AM
K[Keeper β±] -->|watch deadline| AM
K -->|requestAttestation RPN| HUB[IFdcHub]
HUB --> RELAY[Relay Β· Merkle root]
K -->|fetch proof| DA[DA Layer]
K -->|claim guardId, proof| BS
BS -->|verifyReferencedPaymentNonexistence| FDCV[IFdcVerification]
BS -->|make-whole payout| U
FE[Web Β· /integrations/verify] -->|live reads| BS
FE -->|live reads| POOL
classDef flare fill:#0B7A57,stroke:#3ECF9A,color:#fff;
class AM,FTSO,HUB,RELAY,DA,FDCV flare;
Contracts resolve every Flare address through the registry (RegistryResolver); the keeper is a
convenience, not a trust assumption β the claim path is permissionless, so the redeemer or anyone
can submit the proof.
buyGuard β agent misses deadline β keeper requests RPN proof β claim verifies it on-chain β make-whole payout
buyGuard (wallet connected): the premium re-prices live from the FTSO FLR/USD feed as you type β $0.70 β 1.2281 C2FLR, $2.50 β 4.386 C2FLR.
The whole product hinges on one assertion: that the FDC non-existence round-trip actually works on
Coston2. We front-loaded it as a go/no-go gate β scripts/spike.ts exercises
every load-bearing call-site end-to-end and prints PASS/FAIL. Run npm run spike:view (no wallet)
or npm run spike:all (funded).
β PASSED on Coston2 (2026-07-29). All five stages green. The load-bearing leg β
IFdcHub.requestAttestationβ DA-Layer proof βIFdcVerification.verifyReferencedPaymentNonexistenceβ returnedtrueon-chain in 99.3 s (tx0x5774a763β¦9c540a, voting round 1409442). Full benchmark + reproduce steps:DEMO.md.
Beyond the isolated FDC gate, the entire product loop ran live on Coston2 against a genuine FAssets
redemption default β redeem β buyGuard β the assigned agent misses the deadline β keeper proves
non-payment via FDC β claim pays the redeemer make-whole:
β Guard #1 PAID (2026-08-01). Real ticket
redemptionRequestId 42481292(agent0xd5dEβ¦2D64). The keeper reconstructed theReferencedPaymentNonexistencewindow directly from the liveredemptionRequestInfoβ its primary path, not the synthetic fallback β andBackstop.claimpaid 111.55 C2FLR to the redeemer. Claim tx0x5fde024fβ¦(block 33493034). Full tx trail + one-command reproduce (npm run route-b):DEMO.mdΒ·scripts/route-b.ts.
/integrations/verify, live from Coston2 β guard #1 PAID, payout 111.55 C2FLR at block 33493034 (no wallet needed).
| Contract | Address |
|---|---|
Backstop |
0xe7DFfa49EC57f5a9ca349C0F9a170950F052E708 |
BackstopPool |
0x9c1e0f1318141B7dA85207d731157D4853918A9A |
Both source-verified on Blockscout β the exact repo source, including the reentrancy guards and
zero-address checks (Slither: 0 findings). Deploy script: script/Deploy.s.sol.
| Layer | Where | What |
|---|---|---|
| Contracts | src/ |
Backstop (guard lifecycle + claim), BackstopPool (underwriting), PremiumMath, RegistryResolver |
| Keeper | scripts/keeper.ts |
autonomous watcher β detects breaches, requests the RPN proof, submits claim. --once / --dry-run modes (scripts/KEEPER.md) |
| Spike | scripts/spike.ts |
the Day-4 gate harness (stages aβe) |
| Web | web/ |
Next.js dApp reading live Coston2 state, incl. the /integrations/verify proof route |
Both sides of the market, wallet-connected on Coston2:
| Buy a guard β live FTSO premium | Underwrite β live pool position |
|---|---|
![]() |
![]() |
90 unit tests Β· 100% line / statement / function coverage across all four contracts (branch
coverage 98.7% β the one uncovered branch is a reentrancy-guard revert that Foundry can't credit
through the nested re-entry call; the guard itself is exercised by a dedicated test), plus 4
live-Coston2 fork integration tests (test/ForkCoston2.t.sol) against the
real registry, FtsoV2, and AssetManager. The fork tests skip automatically when no COSTON2_RPC_URL
is set, so offline CI stays green (94 tests with a fork).
forge test # 90 offline Β· 94 with a Coston2 RPC
forge coverage --no-match-coverage "(script|test)" --summaryUnit tests exercise Backstop's own logic with mock Flare contracts; the real integration is proven by the fork tests + the Day-4 spike β never mocked-as-real.
# Contracts
forge soldeer install # deps
forge build && forge test # compile + test
cp .env.example .env # fill PRIVATE_KEY (throwaway testnet key), fund at faucet.flare.network/coston2
# Prove the Flare integration end-to-end on Coston2
npm install && npm run spike:all
# Deploy (Blockscout-verified, no API key)
source .env && forge script script/Deploy.s.sol:Deploy \
--rpc-url "$COSTON2_RPC_URL" --private-key "0x$PRIVATE_KEY" --broadcast \
--verify --verifier blockscout --verifier-url https://coston2-explorer.flare.network/api/
# Run the autonomous keeper
npm run keeper:once # single sweep Β· npm run keeper for the watch loop
# Web app
cd web && npm install && npm run dev # http://localhost:3000- Pool solvency under correlated defaults β many agents failing at once can under-fund the pool; mitigated by a per-agent exposure cap (invariant-tested) and a global solvency cap (total coverage β€ 80% of the pool's live USD value, FTSO-priced), both enforced on-chain β bounded, not eliminated.
- Payout latency = FDC round time β make-whole is fast but bounded by the attestation voting round (~99 s measured); we surface the wait in the UI rather than hide it.
- Linear premium model (
base + kΒ·Ο) β a deliberate MVP simplification, flagged in code.
- FBTC / FDOGE coverage β the same RPN machinery generalizes to every FAsset.
- Risk-tranched pools (senior / junior) on top of the existing solvency engine.
- Mainnet pilot with a capped underwriting pool.
MIT Β© 2026

