Skip to content

test: cover sweep-fee floor boundaries and add below-floor metric#4197

Open
piotr-roslaniec wants to merge 2 commits into
feat/follower-sweep-fee-soft-checkfrom
chore/sweep-fee-review-followups
Open

test: cover sweep-fee floor boundaries and add below-floor metric#4197
piotr-roslaniec wants to merge 2 commits into
feat/follower-sweep-fee-soft-checkfrom
chore/sweep-fee-review-followups

Conversation

@piotr-roslaniec

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #4194, addressing the confirmed, actionable findings from a multi-agent review of that PR. Stacked on feat/follower-sweep-fee-soft-check; rebase onto main once #4194 merges.

Scope is deliberately narrow: test coverage for the untested soft check and fee-floor boundaries, plus one small observability add. No behavior of the leader-side floor changes.

Changes

Follower soft check: tests + metric (was untested — review's lead item)

  • Extract the below-floor decision from ValidateDepositSweepProposal into a pure checkSweepFeeFloor helper, and unit-test it directly (just below / exactly at / above the safe minimum, plus missing and zero fee) instead of scraping logger output. The check previously had zero behavioral tests — only a constant-drift guard — so a flipped Cmp or a dropped branch would pass CI silently.
  • Emit a deposit_sweep_fee_below_floor_total counter on the follower path when a proposal is below the floor. The check was log-only; a metric lets operators alert on underpriced proposals during a mixed-version rollout instead of grepping node logs. Reuses the existing follower metricsRecorder; ValidateDepositSweepProposal's signature is unchanged and the node still signs the proposal.

Redemption fee: cap boundary tests

  • EstimateRedemptionFee gains coverage for two boundary outcomes of the safe-minimum floor:
    • buffered fee above the Bridge max is bounded down to the cap (not an error);
    • a raw estimate already above the cap errors before the floor is applied.
  • The second is intended behavior (documented in redemptions.go), but it trades liveness (redemption not attempted this round) for not broadcasting a fee the Bridge would reject. The test pins that tradeoff so it is a visible, regression-safe decision.

Reviewed but intentionally deferred (not fixed here)

  • Follower compares against the static 5*vsize floor, not the buffered estimate. Catching "above floor but underpaid" proposals would require a live fee-oracle query inside proposal validation — the wrong layer, and it introduces non-determinism into validation. Hard enforcement belongs on-chain in the WalletProposalValidator.
  • Soft check covers only 1 of the 4 floored flows (deposit sweeps, not redemptions / moving funds / moved-funds sweeps). Kept as-is per the decision to keep-and-improve the deposit-sweep check; flagged here so the asymmetry is a visible decision rather than an oversight.
  • P2SH deposit vsize underestimation (both leader and follower use isWitness=true) — already documented as a code caveat in fee.go.
  • Integer-truncation before the 25% buffer in applyWalletTxFeeFloor — a no-op for current callers (EstimateFee returns exact multiples); safe to defer.
  • Nil-SweepTxFee branch — defensive; a nil fee fails at ABI packing before the soft check runs, so it is not reachable in production.
  • Mirror constants (tbtc <-> tbtcpg) — already guarded by the drift test added in Add follower-side soft check for below-floor sweep fees #4194.

An overflow concern raised during review was rejected as logically unreachable: the int64(maxTotalFee) cast runs only inside uint64(totalFee) > maxTotalFee, which for an int64 totalFee implies maxTotalFee < MaxInt64, so the cast cannot wrap.

Testing

  • go test ./pkg/tbtcpg/ — pass
  • go test ./pkg/tbtc/ -run 'TestDepositSweepAction|TestCheckSweepFeeFloor|TestSweepFeeConstantsMirrorTbtcpg' — pass
  • go vet / gofmt clean on both packages

The follower-side soft check had no behavioral tests; only a constant
drift guard existed, so a flipped comparison or dropped branch in the
below-floor decision would pass CI silently.

Extract the decision into a pure checkSweepFeeFloor helper so it can be
tested directly instead of by scraping logger output, and cover the
boundary (just below / exactly at / above the safe minimum, plus missing
and zero fee).

Emit a deposit_sweep_fee_below_floor_total counter on the follower path
when a proposal is below the floor, so operators can alert on underpriced
proposals during a mixed-version rollout instead of grepping node logs.
The metric reuses the existing follower metricsRecorder and does not
change ValidateDepositSweepProposal's signature; the check stays log-only
and the node still signs the proposal.
EstimateRedemptionFee had no coverage for two boundary outcomes of the
safe-minimum floor:

- a buffered fee that exceeds the Bridge max is bounded down to the cap
  (not an error), and
- a raw estimate already above the cap errors before the floor is
  applied, rather than broadcasting an underpriced transaction.

The second case is intended behavior (redemptions.go documents it) but
trades liveness for not broadcasting a fee the Bridge would reject;
pinning it in a test makes that tradeoff explicit and regression-safe.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e39ee918-0e99-404b-95a2-79841edb47c1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/sweep-fee-review-followups

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant