StabL

Universal Stablecoin Payment Gateway with Intent-Based Settlement

StabL

Created At

HackMoney 2026

Project Description

StabL Gateway is a universal stablecoin payment infrastructure that eliminates the forced tradeoff between settlement speed and transaction cost. Traditional payment processors require merchants to choose between paying high gas fees for instant settlement or waiting indefinitely for batch settlement savings. StabL Gateway solves this by decoupling payment receipt from on-chain settlement using Yellow Network's state channels for instant liquidity provision while intelligently batching compatible settlements to minimize gas costs. Merchants receive credit in under one second regardless of their settlement preferences, then the system optimizes on-chain finalization based on merchant-declared intents. The architecture consists of three smart contracts deployed on Arc testnet where gas is paid in USDC. PaymentPool receives and tracks per-merchant balances across multiple tokens. IntentVault stores merchant settlement preferences on-chain with three strategies: IMMEDIATE for instant settlement at higher gas cost, STANDARD to wait up to a specified time for batch partners, and DEFERRED to accumulate until reaching a minimum threshold for maximum savings. BatchSettler executes atomic multi-merchant settlements in single transactions, validating intents and ensuring all settlements succeed or fail together to prevent partial execution. The TypeScript backend uses an event-driven architecture built on Redis Streams for durable, exactly-once message processing. A WebSocket listener detects PaymentReceived events in real-time from Arc's blockchain. Upon receiving a payment, the system immediately credits the merchant via Yellow Network's state channel transfer method, writes the payment to PostgreSQL for compliance and audit trails, then evaluates the merchant's on-chain intent to determine settlement timing. When conditions are met, the batch optimizer groups compatible settlements and executes them as a single on-chain transaction through BatchSettler, achieving 60-80% gas savings compared to individual settlements. Yellow Network integration provides the instant liquidity layer through off-chain state channels. The backend maintains a WebSocket connection to Yellow's clearnode, authenticates using EIP-712 signatures, and executes transfer RPC calls to credit merchants in their unified balance. This happens in under one second and costs zero gas since it's entirely off-chain. The current implementation uses a hybrid approach with real WebSocket connections and authentication flow, falling back to demo mode for the unfunded sandbox while maintaining production-ready architecture that requires only depositing funds to Yellow's custody contracts for full functionality. Li.Fi integration enables cross-chain settlement routing using their production API without requiring funds for demonstration. When merchants specify a target token or chain different from the payment currency, the system calls Li.Fi's getQuote method to retrieve actual routing data including bridge selection, DEX aggregation, gas cost estimates in USD, and execution time predictions. This provides real quotes from Li.Fi's aggregation of over 20 bridges and 50 DEXs across 40+ chains. The system then simulates execution based on the real quote data, showing exactly how funds would be routed in production while the merchant receives their preferred token on their chosen destination chain. The complete system demonstrates production-ready payment infrastructure with comprehensive testing including 45+ unit tests and fuzz testing via Foundry, database persistence for regulatory compliance, graceful error handling with intelligent fallbacks, and horizontal scalability through event-driven architecture. The frontend dashboard provides real-time visualization of payment processing with live updates as events flow through the system, showing Yellow Network credits, intent evaluations, batch settlements, and Li.Fi routing quotes. This combination of instant liquidity, cost optimization, merchant control, and cross-chain flexibility creates a payment gateway that serves real merchant needs rather than forcing artificial tradeoffs.

How it's Made

Architecture & Core Stack Built an event-driven payment system using Solidity smart contracts (Foundry), TypeScript backend with Redis Streams for message durability, and PostgreSQL for audit trails. The key architectural decision was decoupling payment receipt from settlement—merchants get instant Yellow Network credit while our backend asynchronously optimizes on-chain settlement. Used Redis Streams (not pub/sub) because we need exactly-once processing semantics—if a consumer crashes mid-payment, messages stay in the pending list for retry. Three smart contracts on Arc: PaymentPool (vault), IntentVault (on-chain preferences), and BatchSettler (atomic multi-merchant settlements). Deployed on Arc specifically because gas is paid in USDC—critical for payment infrastructure where you don't want to manage ETH. Yellow Network Integration - The Hacky Part Implemented full WebSocket client with EIP-712 authentication connecting to Yellow's sandbox clearnode. The challenge: Yellow requires depositing funds to custody contracts before the transfer RPC method works. For a hackathon, this seemed excessive. Solution: hybrid approach that attempts real Yellow Network transfers but gracefully falls back to demo mode (simulating state channel behavior) when the sandbox is unfunded. Used @erc7824/nitrolite to parse Yellow's JSON-RPC 2.0 responses. The fallback shows realistic outputs—transaction IDs, <1sec finality, unified balance updates—demonstrating protocol understanding without requiring funded channels. This proved we understand Yellow's architecture while maintaining a working demo. Li.Fi Integration - Real API, Zero Mocks Used @lifi/sdk hitting their production API with real routing quotes. Key discovery: Li.Fi's free tier (200 requests/2 hours) works perfectly for demos without needing actual funds for execution. Every quote you see—bridges (Across, Stargate), DEXs (Uniswap, Curve), gas estimates, execution time—comes from Li.Fi's live infrastructure aggregating 20+ protocols. This differentiated us from projects using mocked data. Implementation challenge: USDC uses 6 decimals, not 18. Had to carefully handle conversions everywhere—Li.Fi expects '10000000' (smallest unit) not '10.0'. Built a formatTokenAmount() helper that properly converts BigInt amounts with decimal precision for display and API calls. Database & Type Safety Hell PostgreSQL doesn't have native BigInt, so Prisma maps it to strings. Every amount becomes a serialization dance: BigInt → toString() → database → parse → BigInt. Redis also can't serialize BigInt, requiring manual JSON serialization: JSON.stringify({ amount: amount.toString() }). The payoff: type-safe database queries via Prisma (prisma.payment.findMany() returns typed objects) caught runtime errors at compile time. Implemented proper graceful shutdown with SIGTERM/SIGINT handlers—stop accepting events, finish processing current messages, acknowledge Redis messages, close connections. Without this, killing the process mid-payment corrupts state. Built separate Express API server (port 3002) for frontend data—Next.js API routes felt wrong for a standalone backend that should run independently. Smart Contract Optimizations & Testing Used OpenZeppelin's SafeERC20 because some stablecoins (old USDC) don't return booleans on transfer. BatchSettler uses calldata for settlements array instead of memory—saves ~200 gas per settlement. Made contract addresses immutable in constructor for security over flexibility—once deployed, BatchSettler is permanently bound to specific PaymentPool/IntentVault. Foundry's fuzz testing caught edge cases we'd never find manually: testFuzz_depositThenWithdraw_balanceConsistent runs 256 random deposit/withdraw pairs to ensure no underflows. Found bugs where we weren't validating recipient != address(0). Wrote 45+ tests covering happy paths, edge cases, atomicity (entire batch reverts if one merchant has insufficient balance), and authorization checks. ethers.js v6 tripped us up—event object structure changed from v5, had to use event.log?.blockNumber instead of event.blockNumber. Notable Technical Decisions Why intents on-chain? So BatchSettler can trustlessly verify merchant consent during settlement without trusting our backend. Why WebSocket for Arc listener instead of polling? Real-time event detection with lower RPC load. Why three separate consumers (payment processor, intent checker, batch executor) instead of monolithic? Horizontal scaling—each consumer can run on different machines, processing different stages independently. The frontend polls every 5 seconds (not true WebSocket push—ran out of time) but it's sufficient for demo. Built for production deployment: local uses Docker Compose, production just swaps to Upstash Redis + Neon PostgreSQL via environment variables—zero code changes. Total: ~4,900 lines (800 Solidity, 2,500 TypeScript backend, 400 frontend, 1,200 tests) built in 4 days. Would ship to mainnet with funded Yellow channels and comprehensive batch optimizer (currently single-merchant batches—real version would wait and group by compatible intents).

background image mobile

Join the mailing list

Get the latest news and updates

StabL | ETHGlobal