Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Backstop logo β€” open the live app

Backstop πŸ›Ÿ

Redemption insurance for FXRP β€” if your redemption agent never delivers XRP, Flare's own on-chain proof pays you make-whole

Backstop β€” open the live app

Live Web App Pitch Deck YouTube Demo FDC Gate PASSED Real Claim PAID Deployed on Coston2 Flare Summer Signal DoraHacks BUIDL


Solidity Foundry Next.js TypeScript Tests Coverage License CI/CD Release


⚠️ The problem

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.

πŸ›Ÿ The solution

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.

πŸ‘€ Who it's for

  • Primary β€” the FXRP redeemer. Anyone converting FXRP back to native XRP through the FAssets redemption queue, and especially trading desks and treasuries redeeming at size, for whom a single agent default is a real balance-sheet event. Concretely: the wallet that calls AssetManager.redeem() and then has to wait and hope the agent delivers on XRPL.
  • Secondary β€” the underwriter (LP). FLR holders wanting yield uncorrelated with token price. They fund the pool, earn redemption premiums, and are protected by an on-chain per-agent exposure cap and a global solvency cap.
  • Downstream β€” FAssets integrators. Lending markets, DEXes and custodians that would rather quote FXRP redemption risk than absorb it. buyGuard is callable by any contract β€” Backstop is a protocol, not just an app.

πŸ”₯ Why this needs Flare β€” and only Flare

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.

πŸ—οΈ Architecture

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;
Loading

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.

πŸ” The one flow

buyGuard β†’ agent misses deadline β†’ keeper requests RPN proof β†’ claim verifies it on-chain β†’ make-whole payout

buyGuard premium re-pricing live from FTSO as coverage changes
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.

βœ… Proof: the Day-4 FDC gate (PASSED)

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 β€” returned true on-chain in 99.3 s (tx 0x5774a763…9c540a, voting round 1409442). Full benchmark + reproduce steps: DEMO.md.

βœ… Proof: a real end-to-end claim (PAID, on-chain)

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 (agent 0xd5dE…2D64). The keeper reconstructed the ReferencedPaymentNonexistence window directly from the live redemptionRequestInfo β€” its primary path, not the synthetic fallback β€” and Backstop.claim paid 111.55 C2FLR to the redeemer. Claim tx 0x5fde024f… (block 33493034). Full tx trail + one-command reproduce (npm run route-b): DEMO.md Β· scripts/route-b.ts.

/integrations/verify reading live Coston2 state: guard #1 PAID and the claim payout card
/integrations/verify, live from Coston2 β€” guard #1 PAID, payout 111.55 C2FLR at block 33493034 (no wallet needed).

πŸš€ Deployed on Coston2 (chain 114) β€” verified source

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.

🧩 Components

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
Buy a guard Underwrite the pool

πŸ§ͺ Testing

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)" --summary

Unit 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.

⚑ Getting started

# 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

βš–οΈ Honest limitations

  • 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.

πŸ†• What was newly built during the program

Everything. Backstop did not exist before this hackathon β€” no prior codebase, nothing ported, nothing carried over. First commit b2fed37 is dated 2026-07-25, inside the program window (development opened June 29, submission closes August 14). The whole history is public and reviewable:

git log --reverse --format="%h %ad %s" --date=short | head
Before Built during the program
Smart contracts nothing 554 lines of Solidity across 4 contracts
Flare integration nothing 6 engine-class methods (FDC Γ—3, FAssets, FTSO v2, Registry)
Tests nothing 94 tests β€” 90 unit (100% line/stmt/func coverage) + 4 live-fork, plus 128k-call invariant runs
Keeper nothing TypeScript/viem autonomous watcher: deadline β†’ RPN request β†’ DA-Layer poll β†’ claim
Web app nothing Next.js App Router frontend incl. the public /integrations/verify proof route
Deployments nothing Both contracts deployed and source-verified on Coston2

Third-party code is dependencies only (flare-periphery, OpenZeppelin, Foundry, viem/wagmi, Next.js) β€” no application logic borrowed.

Milestones, all on-chain: Day-4 FDC gate passed 2026-07-29 (99.3 s round-trip, round 1409442) Β· full end-to-end claim 2026-08-01 (guard #1 PAID, 111.55 C2FLR, block 33493034) Β· contracts hardened and redeployed after clearing all 30 Slither findings.

πŸ—ΊοΈ Roadmap

The economics already shipped β€” live parameters, readable on-chain from the deployed contract:

Parameter Live value Meaning
baseBips / kBips / sigmaBips 100 / 50 / 2000 premium = base + kΒ·Οƒ = 110 bips = 1.10% of coverage
agentCapUsd $100,000 max exposure to any single agent vault
maxUtilizationBips 8000 total coverage ≀ 80% of live pool USD value

A desk redeeming $10,000 of FXRP pays $110 to be made whole; the pool holds $1.25 for every $1 of coverage written.

Next, in dependency order:

  1. Calibrate Οƒ against real default history. The 20% volatility figure is an honest MVP placeholder β€” fit it to measured FAssets agent default frequency before pricing real risk.
  2. External audit of the claim gate and pool share accounting. 94 tests, invariant runs and a clean Slither report are a floor, not a substitute β€” and a hard prerequisite to mainnet.
  3. Capped mainnet pilot post-audit: hard pool ceiling, existing caps, prove the loss ratio over a real quarter before lifting anything.
  4. FBTC / FDOGE coverage β€” the RPN machinery is asset-agnostic and generalizes to every FAsset.
  5. Risk-tranched pools (senior / junior) once underwriting demand justifies splitting the curve.

πŸ“„ License

MIT Β© 2026

About

πŸ›Ÿ Backstop β€” FXRP redemption-default insurance on Flare, triggered by the protocol's own FDC ReferencedPaymentNonexistence proof (Coston2).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages