ENSRouter

ENSRouter: Pay any ENS name in USDC — auto-routed to their preferred chain & tokens.

ENSRouter

Created At

HackMoney 2026

Winner of

LI.FI

LI.FI - Best LI.FI-Powered DeFi Integration 1st place

ENS

ENS - Integrate ENS

Prize Pool

Project Description

ENSRouter is a cross-chain payment routing platform built on Ethereum Name Service (ENS) that simplifies how people receive crypto payments across multiple blockchains.

The Problem

In today's multi-chain world, receiving crypto payments is painful. If someone wants to pay you, they need to know your wallet address, which chain you prefer, and which token you want. If they're on a different chain, they have to manually bridge and swap, a slow, confusing, and error-prone process. Recipients end up with funds scattered across chains in tokens they didn't want.

The Solution

ENSRouter lets recipients configure their payment preferences once on their ENS name. They specify:

  1. Which chain they want funds on (Ethereum, Base, Arbitrum, Polygon, or Optimism)
  2. Which tokens they want and in what proportions (e.g., 60% USDC, 30% ETH, 10% DAI)
  3. Slippage tolerance for token swaps

These preferences are stored directly on-chain as ENS text records, making them decentralized, portable, and universally readable.

When a sender wants to pay, they simply enter the recipient's ENS name (e.g., alice.eth), choose how much USDC to send, and ENSRouter handles everything else, bridging funds cross-chain via the LI.FI SDK, swapping into the recipient's preferred token allocations, and delivering the final tokens to their wallet. The sender gets a real-time progress tracker showing each step: approval, swap, bridge, and delivery.

Key Features

  1. One-time profile setup: Recipients connect their wallet, select their destination chain and token allocations via an intuitive slider UI, and write their preferences to ENS text records.
  2. Shareable payment links and QR codes: Each profile generates a direct payment URL (/send/alice.eth) and QR code for easy sharing.
  3. Cross-chain routing via LI.FI: The platform uses LI.FI's aggregation protocol to find optimal routes for bridging and swapping in a single transaction, with built-in slippage protection.
  4. Real-time payment tracking: A step-by-step status tracker shows senders exactly where their payment is in the pipeline.
  5. Telegram notifications: Recipients link their ENS to a Telegram bot and receive instant notifications when payments arrive or fail, complete with transaction hashes and block explorer links. Link to the bot: t.me/ENSRouterBot
  6. Webhook-based event processing: Bridge events are signed with HMAC-SHA256 and processed by the backend, which maintains a full transaction audit trail in MongoDB with a notification retry queue.

Architecture

The frontend is a Next.js application using Wagmi and RainbowKit for wallet connectivity, with the LI.FI SDK handling all bridge and swap execution client-side. The backend is an Express.js API that manages ENS resolution and caching, transaction record-keeping, webhook processing, and Telegram bot operations. All user preference data lives on-chain via ENS text records, while operational data (transaction history, Telegram linkages, notification queues) is stored in MongoDB.

In Essence

ENSRouter turns any ENS name into a smart payment endpoint. Instead of asking "what's your address, what chain, what token?", senders just need to know your .eth name, and the protocol handles the rest.

How it's Made

ENSRouter was built as a full-stack TypeScript application with a Next.js 16 frontend and an Express.js backend, connected by webhooks and a shared MongoDB database.

The core idea is that payment preferences live on-chain as ENS text records. On the frontend, we use Wagmi's useEnsText hook to read three custom text records from Ethereum mainnet: ENSRouter.chain (the recipient's preferred destination chain), ENSRouter.tokenAlloc (a comma-separated string like "USDC:60,ETH:30,DAI:10"), and ENSRouter.slippage (their slippage tolerance). To write these records, we call the ENS Public Resolver's multicall function at 0xF29100983E058B058B709F3D539b0c765937B804AC15, batching three setText calls into a single transaction using viem's encodeFunctionData and namehash. This means recipients only pay gas once to set up their entire payment profile. If the user is on the wrong chain, the hook auto-switches to Ethereum mainnet via Wagmi's switchChainAsync before submitting.

Partner Technologies:

  1. ENS (Ethereum Name Service): ENS is the backbone of the entire project. Instead of building a custom registry or database for payment preferences, we store everything directly in ENS text records. This gives us decentralized, censorship-resistant profile storage that any other application can read. On the backend, we use ethers.js v6 to resolve ENS names and fetch text records like avatar, twitter, and telegram handles, with a 5-minute in-memory cache to reduce RPC calls. On the frontend, Wagmi's native ENS hooks (useEnsAddress, useEnsText, useEnsName, useEnsAvatar) let us read profiles reactively. The ENS integration means a user's payment profile is portable — it's not locked into our platform. Anyone can read alice.eth's ENSRouter.chain record and know where to route funds.

  2. LI.FI: LI.FI is the cross-chain execution engine. We initialize the LI.FI SDK with our Wagmi wallet client as the EVM provider, so it can sign transactions directly through the user's connected wallet. When a payment is triggered, the flow works like this: we call getQuote() with the source chain USDC address, destination token address, amount in wei, and the recipient's wallet as the toAddress. The quote comes back with fee estimates and execution duration, which we display in a payment preview component using TanStack React Query with 30-second stale time for live pricing. When the user confirms, we call convertQuoteToRoute() then executeRoute() with an updateRouteHook callback. This callback fires on every state change during execution, and we map LI.FI's internal process types (TOKEN_ALLOWANCE, SWAP, CROSS_CHAIN, RECEIVING_CHAIN) to user-friendly step names displayed in a real-time progress tracker. LI.FI handles the complexity of finding the best bridge or DEX route, managing token approvals, and executing cross-chain transfers — we just feed it parameters and track the output.

The payment splitting logic works by calculating each token's USDC share from the allocation percentages, then executing transfers sequentially. For each allocation, there are three possible paths: if the sender is on the same chain and the token is USDC, we do a direct ERC-20 transfer using Wagmi's writeContractAsync. If the sender is on the same chain but the token is different (e.g., ETH), we route through LI.FI for a same-chain swap. If the sender is on a different chain, LI.FI handles the bridge plus optional swap in one route.

One notably hacky thing we built is the USDC fallback mechanism. If a swap to a non-USDC token fails (say the liquidity pool is dry for a particular token on the destination chain), instead of failing the entire payment, we catch the error and automatically retry the transfer but sending USDC instead. The UI resets its step tracker, shows a warning toast, and re-executes either as a direct transfer (same chain) or a USDC-to-USDC bridge (cross chain). This means the recipient always gets their money even if the exact token split cannot be fulfilled.

The wallet connection layer uses RainbowKit v2 with Wagmi v3 configured across five chains: Ethereum mainnet, Base, Arbitrum, Polygon, and Optimism. Each chain has its own Alchemy RPC transport for reliable node access. The Wagmi config is shared between the app and the LI.FI SDK initialization, so chain switching during LI.FI execution works seamlessly.

On the backend, the Express server handles three responsibilities. First, the ENS service resolves names and caches results using ethers.js. Second, the webhook service receives bridge status events from the frontend (bridge.step, bridge.complete, bridge.failed), verifies them with HMAC-SHA256 signatures using constant-time comparison to prevent timing attacks, and upserts the full transaction state into MongoDB. Third, the Telegram bot (built with Telegraf) runs in webhook mode for production (Render deployment) and lets recipients link their ENS name via /link commands. When a payment completes, the webhook service adds it to a NotificationQueue collection, attempts immediate delivery, and if that fails, a background job retries every 30 seconds up to 5 times.

The MongoDB schemas use strategic indexing: transactions are indexed on id (unique), recipient, and status for efficient notification queries. The notification queue uses unique transactionId indexes and sparse indexes on recipientENS. Users have a unique index on ensName and sparse indexes on telegramChatId to support the Telegram linking flow.

The frontend UI includes some visual touches: a Three.js dithered animated background using React Three Fiber, allocation sliders for setting token percentages, QR code generation for payment links via qrcode.react, and toast notifications via Sonner that include clickable links to block explorers (Etherscan, Basescan, Arbiscan, Polygonscan, Optimistic Etherscan) for every transaction hash.

The whole system is designed so that the on-chain ENS records are the source of truth for payment preferences, LI.FI handles all the cross-chain complexity, and the backend is purely for notifications and transaction history — the payment itself is fully client-side and non-custodial.

background image mobile

Join the mailing list

Get the latest news and updates

ENSRouter | ETHGlobal