From ba624d3f5e90676776a2da3f90156e49cbc9b6a2 Mon Sep 17 00:00:00 2001 From: grandizzy Date: Thu, 26 Mar 2026 12:22:45 +0200 Subject: [PATCH] fix: return 410 ChannelClosed for zero-deposit settled channels During settlement the escrow contract may zero the deposit before setting the finalized flag. This creates a window where finalized=false but deposit=0. Without this guard, vouchers against such channels return 402 AmountExceedsDepositError instead of 410 ChannelClosedError. The 410 response tells clients to clear their local channel state and open a fresh channel on the next request, which is the correct recovery path. --- src/tempo/server/Session.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tempo/server/Session.ts b/src/tempo/server/Session.ts index ea4fb7e3..eb3c5065 100644 --- a/src/tempo/server/Session.ts +++ b/src/tempo/server/Session.ts @@ -456,6 +456,15 @@ async function verifyAndAcceptVoucher(parameters: { if (onChain.closeRequestedAt !== 0n) { throw new ChannelClosedError({ reason: 'channel has a pending close request' }) } + // Treat a zero deposit on an existing channel as settled/closed. + // During settlement the escrow contract may zero the deposit before + // setting the finalized flag, creating a brief window where + // finalized=false but deposit=0. Without this guard the voucher + // check below would return a 402 (AmountExceedsDepositError) instead + // of the correct 410 (ChannelClosedError). + if (onChain.deposit === 0n && onChain.payer !== '0x0000000000000000000000000000000000000000') { + throw new ChannelClosedError({ reason: 'channel deposit is zero (settled)' }) + } if (voucher.cumulativeAmount <= onChain.settled) { throw new VerificationFailedError({