Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Payout melts and drain ignore mint input fees (balance_tolerance_percent is accidental compensation)

Open
#414 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
30/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Active
Tech stack
go

Research direction

Read src/merchant/merchant.go, especially processPayout and PayoutShare (lines 335–347 and 428–435), then inspect DrainMint (943–979) and the wallet fee handling added for #409. Start by comparing the existing payout and drain behavior with a fee-charging wallet; the issue leaves the accounting approach to a maintainer decision. Done means the chosen fee treatment is explicit and covered by tests, including a 100-ppk mint and protection of min_balance.

Written by the indexing model from the issue text.

Description

Fee-economics gap (surfaced by #409/#413): payout melts and drain ignore mint input fees — aimed amounts overstate what a fee-charging mint will actually pay.

Code path (verified on main): processPayout (src/merchant/merchant.go:335–347) computes aimedPaymentAmount := balance - mintConfig.MinBalance from the wallet's face-value balance, and PayoutShare (merchant.go:428–435) melts exactly that amount with MeltToLightning(mint, aimedPaymentAmount, maxCost, addr). At a mint charging input_fee_ppk, melting N sats consumes N + ceil(Σppk/1000) of proofs — the same fee #409 now handles on the incoming side. Nothing on the outgoing side accounts for it:

  • balance_tolerance_percent (added to aimedPaymentAmount as maxCost) is the only thing standing between the payout and failure/underpayment at fee-charging mints — a percentage knob doing accidental fee compensation, not fee accounting.
  • DrainMint (merchant.go:943–979) explicitly uses the wallet Drain "which doesn't include fees" (merchant.go:953) — the returned amount is face value.
  • Pricing (price_per_step + margin) prices the incoming swap fee implicitly at best; the operator's outgoing melt fee per payout cycle is unpriced. On a busy router at a 100-ppk mint this is a small but permanent leak out of min_balance.

Repro vehicle: the cloud lab now has a fee-charging mint (#413, mint-fees, input_fee_ppk=100); the signet lane (see the CLN/rune lane issue) makes it real. Unit-level: a PayoutShare test with a stubbed wallet that charges a melt input fee and asserts the aimed amount fails or dips into min_balance.

Live evidence for the premise: mint.coinos.io charges input_fee_ppk=100 (the #409 observation); our own signet mint testnut.cashu.exchange currently charges 0 on all keysets (verified GET /v1/keysets today) — so the gap is invisible in our current testing and only materializes against real-world mints.

Suggested fix shapes (maintainer decision):

  1. Fee-aware aim: before melting, query the wallet's proof-set fee (the SwapFeeSats primitive from #409 generalizes to "fee to spend wallet proofs at mint X") and aim for balance − fee − min_balance.
  2. Fee-aware pricing: fold an expected per-payout fee into price_per_step/margin accounting (config or docs), keeping melts as-is.
  3. Document the tolerance: if balance_tolerance_percent is deemed sufficient, document it as the fee mitigation and add a lab test pinning that a 100-ppk mint still pays out within tolerance.

Why an issue, not a PR: choosing between accounting-in-code vs pricing-in-config is a product/economics decision, and shape 1 extends a wallet-port interface that just gained a method in #409 — better decided once #409/#413 land.

Refs: #409 (incoming-side fee handling), #413 (fee-charging lab mint), #339 (v0.6.0 scope).

Dominant language
Go
Stars
12
Forks
14
Avg merge
1d 5h
Merged PRs (30d)
246

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenTollGate/tollgate-module-basic-go

All issues in OpenTollGate/tollgate-module-basic-go

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.