Skip to content

Repository files navigation

FreeFlo Protocol

Permissionless, intent-based on-chain ↔ off-chain interoperability.

CI Status License: MIT

FreeFlo is currently on MVP stage. Meaning that some trade-offs had to be made to prove this actually works:

  • The current provider for Instant SEPA transfers doesn't allow for API execution of payment for non-trusted beneficiaries. Receiver's details have to be stored with the provider pre-transfer.
  • Attestation Service is running on a dedicated server creating a single point of failure. The goal is to have this running on a TEE.
  • The current Solver implementation allows solvers to set their own ForEx rate. Future implementation will have an enshrined oracle for each currency.

Overview

FreeFlo is a trust-minimized, intent-powered off-ramp protocol enabling USDC ↔ Fiat swaps.

Unlike cross-chain protocols where both input and output occur on-chain, FreeFlo settles the output leg off-chain via real-time payment networks (RTPNs), with fulfillment proven cryptographically using TLSNotary.

FreeFlo's MVP currently supports just the one RTPN: Instant SEPA which enables real-time EURO payments across european banks.

Note: MVP end-to-end settlement ( testnetUSDC <> EURO swap): ~10-15 seconds.

Key Properties

  • Permissionless: Anyone with an account form supported RTPNs can run a solver.
  • Trust-minimized: Payment verification via zkTLS proofs, not trusted third-parties required.
  • Non-custodial: Users crypto is escrowed in smart contracts and only released if off-chain payment is cryptographically proven.
  • RTPN-agnostic: Extensible to any real-time payment network with API ( for automation) and TLS ( for proof generation) capabilities.

Dictionary

Term Definition
Intent A user's request to convert USDC to fiat at a specified destination: RTPN, fiat currency, and recipient details.
Solver An entity that fulfills intents by sending fiat and proving payment.
Quote A solver's offer to fulfill an intent, specifying the amount to be sent in the requested fiat currency
Commitment User's selection of a specific quote, locking USDC for the duration of the fulfillment window
Fulfillment Completing an intent: sending fiat, generating proof, submitting it on-chain, and claiming USDC
Attestation An EIP-712 signed statement from an authorized witness confirming payment was verified via zkTLS
Witness The authorized signer (controlled by FreeFlo Protocol) that validates zkTLS proofs and signs attestations
RTPN Real-Time Payment Network: an off-chain payment network with near-instant settlement (e.g., Revolut, Wise...)
Nullifier A unique payment identifier preventing double-claims, derived from the provider's transaction ID

System Architecture

System Diagram

Component Overview

Component Location Responsibility
OffRampV3 contracts/src/OffRampV3.sol Intent lifecycle, USDC escrow, quote management
PaymentVerifier contracts/src/PaymentVerifier.sol EIP-712 verification, witness registry, nullifier tracking
Attestation Service attestation/ zkTLS proof validation, on-chain state verification, attestation signing
Solver solver/ Quote API, fiat execution, proof generation, intent monitoring
Prover providers/prover/ TLSNotary proof generation per RTPN
Frontend frontend/ Web application for users

Intent Lifecycle

  1. PENDING_QUOTE — User calls createIntent(), deposits USDC. Solvers call submitQuote() with competing offers.

  2. COMMITTED — User calls selectQuote(), locks funds to chosen solver. Solver has fulfillment window to complete.

  3. FULFILLED — Solver sends fiat, proves via zkTLS, calls fulfillIntentWithProof(). Contract verifies attestation, releases USDC to solver.

  4. CANCELLED / EXPIRED — Timeout reached without fulfillment. User calls cancelIntent(), USDC returned.

Security Model

FreeFlo separates concerns between untrusted solvers and trusted infrastructure:

Actor Trust Responsibility
Solver Untrusted Execute fiat transfers, generate proofs
Attestation Service Trusted (FreeFlo) Validate proofs, verify on-chain state, sign attestations
Smart Contracts Trustless Verify signatures, enforce time windows, release funds

Solver Protections

Solvers cannot:

  • Forge payment proofs : TLSNotary proofs are cryptographically bound to the TLS session
  • Claim without valid attestation : On-chain signature verification required
  • Double-claim payments : Nullifier (payment ID) tracked on-chain
  • Claim for wrong intent : Attestation includes intent hash

User Protections

Users are protected against:

  • Solver non-fulfillment : Funds auto-release after timeout via cancelIntent()
  • Quote manipulation : Committed quote amount verified in attestation
  • Incorrect payment amount : Attestation service validates proof amount ≥ committed amount

Risk Considerations

Risk Mitigation
Attestation service downtime Solvers cannot claim, but user funds remain safe. Timeout allows cancellation.
Proof-generation failure No mitigation yet but leaning towards extension of fulfillment window and optimistic settlement ( requires slashing)
Solver commits but never sends fiat Commitment timeout returns funds to user automatically.
Solver underpayment Attestation service validates on-chain committed amount against proof.
Witness key compromise Single point of failure. Future: threshold signatures or TEE.

Quick Start

Prerequisites

  • Node.js 20+
  • Rust 1.75+ (for attestation service and TLSNotary)
  • Foundry

Setup

# Clone
git clone https://github.com/MontaguSandwich/FreeFlo.git
cd FreeFlo

# Install dependencies
cd contracts && forge install && cd ..
cd solver && npm install && cd ..
cd frontend && npm install && cd ..

# Configure environment
cp solver/env.example solver/.env
cp frontend/env.example frontend/.env.local
# Edit .env files with your values

# Start services
cd solver && npm run dev:v3      # Terminal 1: Solver
cd frontend && npm run dev       # Terminal 2: Frontend

# Open http://localhost:3000

See Solver Onboarding Guide for production deployment.

Extending FreeFlo

FreeFlo is designed to support any RTPN with API capability.

Adding a New Payment Provider

  1. Implement the Prover — Create a TLSNotary prover in providers/prover/adapters/<provider>/:

    // Must generate a Presentation proving:
    // - Transaction ID
    // - Amount in cents
    // - Beneficiary identifier (IBAN, account number, etc.)
  2. Register the Server — Add the provider's API domain to ALLOWED_SERVERS in attestation config

  3. Implement Solver Integration — Add provider execution logic in solver/src/providers/<provider>.ts:

    // Must implement:
    // - OAuth/auth flow
    // - Transfer execution
    // - Prover invocation
  4. Register RTPN On-Chain — Solvers declare supported RTPNs via setSolverRtpn()

See providers/README.md for detailed integration guide.

Deployed Contracts

Base Sepolia (Testnet)

Contract Address
OffRampV3 0x34249F4AB741F0661A38651A08213DDe1469b60f
PaymentVerifier 0xd72ddbFAfFc390947CB6fE26afCA8b054abF21fe

Documentation

Document Description
Providers Supported providers
Solver Onboarding Run your own solver
Operations Runbook Production operations

Development

Build

cd contracts && forge build
cd solver && npm run build
cd attestation && cargo build --release
cd frontend && npm run build

Test

cd contracts && forge test -vvv
cd solver && npm test
cd attestation && cargo test

Lint

cd contracts && forge fmt --check
cd solver && npm run lint

License

MIT License. See LICENSE.

Acknowledgments

  • TLSNotary — Privacy-preserving TLS proofs
  • ZKP2P — Research and inspiration
  • OIF — Research, inspiration and Intent-based architecture

About

v0.1 FreeFlo - Permissionless, intent-based on-chain ↔ off-chain interoperability.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages