L402-over-eth-Layer2

Hi magicians,

I’ve opened a new topic for l402 (x402 wrapped BTC) over layer 2.

I am working on it (with LLM yes as i am not a monkey!).

I’d like to share a small project and get feedback from people who know payment channels, EIP-712 and account abstraction much better than I do.

Why

I run LightPhon, an LLM provider aimed at agent orchestrators, with per-use pricing well below the usual subscription/API competitors. On Bitcoin, agents already pay for it machine-to-machine over Lightning, using the L402 pattern: HTTP 402 challenge → pay → retry with a macaroon + proof of payment.

I needed the same thing on Ethereum. Many agent builders live in the EVM world and if somebody don’t want to run a Lightning node it has got another option.

The constraint is the same as on Lightning, though. An agent that calls a tool thousands of times a day can’t send a transaction per call: gas would cost more than the service, and it would add ~1–2 s of latency to every request.

How

L402-EL2 keeps the L402 wire format (so existing parsers still work) but replaces the Lightning invoice/preimage with a unidirectional payment channel on an L2:

  • Escrow contract (L402Escrow.sol): the agent opens a prefunded channel toward a provider (1 L2 tx). channelId = keccak256(abi.encode(payer, provider, token)), so it can be computed offline.
  • Cumulative EIP-712 vouchers as the proof of payment: Voucher(channelId, cumulativeAmount, nonce, validUntil). Each call signs a new total, so there’s no replay, the server keeps one row per channel, and verification is an in-memory signature check (~ms, no RPC).
  • Macaroons for the HTTP credential: caveats (tool, max_cumulative, expires_at, …), fail-closed evaluation, and attenuation, so an agent can hand a narrower token to a sub-agent.
  • On-chain session keys: authorizeSigner(key, maxCumulative, validUntil) puts the spending cap in the contract, not in the client. Revocations/tightening respect the same 24h challenge period as channel closes, so they can’t be used to void vouchers already served.
  • Batch settlement: a settler collects the latest voucher of many channels in one settleBatch().
  • Works with EOAs and ERC-4337 accounts (ERC-1271 verification), plus ERC-2612/ERC-3009 single-signature deposits.
  • MCP integration: initialize/tools/list stay free for discovery; only tools/call, resources/read and prompts/get are billed.

Net effect: 2 on-chain transactions per channel lifecycle (open + settle) instead of one per call, and < 10 ms of payment overhead per request. The token is any ERC-20; I’m using wrapped BTC (cbBTC/WBTC/tBTC) to stay denominated like the Lightning side.

The repo includes the contract (node + Foundry tests, including fuzzing), TypeScript server/client/settler packages, a protocol spec, and an end-to-end example that runs on an in-process EVM with no configuration.

Repo: GitHub - ddorigoddorigo/L402-over-eth-L2: a protocol for token net payments (like L402) for stablecoin instead of Lightning net · GitHub

Not audited — please don’t use it with real funds yet.

Feedback are welcome. More trouble you found more i learn…

Thanks for reading. Happy to answer questions.

Disclosure: I’m the founder of LightPhon, which is the reason I built this and i will use it future.

PS i am a newbie here the site: https://www.l402-over-eth-l2.com/