From 7d8cd769e6cf91dda70fdf06db72a0b03e263dd7 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 10 Jul 2026 22:56:12 -0700 Subject: invoices: reject sub-300-sat on-chain invoice amounts On-chain deposits below 300 sats are dropped by the dust filter in the confirm/credit path, so a specific-amount bitcoin/liquid invoice under that threshold can never be credited. Reject creating one at generation time and point the user at lightning. Any-amount (0) addresses are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/invoices.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/invoices.ts b/lib/invoices.ts index 79bf6f19..fb81914f 100644 --- a/lib/invoices.ts +++ b/lib/invoices.ts @@ -53,6 +53,18 @@ export const generate = async ({ invoice, user }) => { if (!rate) rate = rates[currency]; if (fiat) amount = Math.round((SATS * fiat) / rate); if (amount < 0) fail("invalid amount"); + // On-chain deposits below 300 sats are silently dropped by the dust filter in + // the /confirm credit path (routes/payments.ts), so reject creating a bitcoin/ + // liquid invoice for a specific sub-300-sat amount rather than letting a + // deposit vanish. amount = 0 (any-amount address) is unaffected. + if ( + (type === PaymentType.bitcoin || type === PaymentType.liquid) && + amount > 0 && + amount < 300 + ) + fail( + "On-chain deposits must be at least 300 sats. Use a Lightning invoice for smaller amounts.", + ); if (tip < 0) fail("invalid tip"); if (rate < 0) fail("invalid rate"); if (memo && memo.length > 5000) fail("memo too long"); -- cgit v1.2.3