Skip to content

docs: close the burn nonce before failing a pre-burn USDC transfer [RAI-3128] - #1706

Open
JuaniRios wants to merge 1 commit into
rai-2998-board-logsfrom
rai-3128-burn-fail-nonce-close
Open

JuaniRios wants to merge 1 commit into
rai-2998-board-logsfrom
rai-3128-burn-fail-nonce-close

Conversation

@JuaniRios

@JuaniRios JuaniRios commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Part of RAI-3128.

Before an operator fails a USDC transfer stuck at BridgingSubmitting, the runbook now asks for a nonce check on more than one RPC provider and a self-transfer that closes the nonce, and the recovery text in the SPA and the board says not to fail until those steps are done. #1704 (RAI-3125) added the same steps for the Base to Alpaca withdrawal. This PR adds them for the burn.

Live effect: operator guidance only, no bot code · Risk: medium (guidance on a funds path: a transfer failed after a burn nobody saw strands that USDC, and the steps replace a wallet transaction) · Ships: runbook on merge, board when the observability workflow succeeds, dashboard text on the next dashboard release · Blocks: needs the RAI-2998 stack below it

Decisions

  • Both directions in the runbook. The runbook paragraph covers both directions, and a Base to Alpaca burn has the same gap on Base. So the step names the chain of the burn. cli-ops.md
  • One copy where the runbook has it. For Alpaca to Base the steps live only in the runbook, and the dialogs carry a short gate that points to it. The Base to Alpaca withdrawal procedure is completed in the runbook by docs: check WithdrawV2 too before failing a Base to Alpaca USDC transfer [RAI-3125] #1704, which is not below this PR, so until then the dialog keeps the full Base to Alpaca text.
  • Stop before any wallet transaction. Self-transfers and an offline late-burn mint run with the bot stopped, since they send from the bot's wallet. With the bot running, the late mint uses the live complete-mint route, which takes the recovery lock. A gap nonce is checked for a kept send before it is filled.
  • When not certain, resume. At BridgingSubmitting, transfer resume --kind usdc adopts a burn that landed and never sends a second burn. If it finds none, it stops and the transfer stays where it is.
  • One PR for the issue. RAI-3128 asked for two PRs. I kept the runbook and the dialog text together, one PR per issue. The runbook change merges cleanly with docs: check WithdrawV2 too before failing a Base to Alpaca USDC transfer [RAI-3125] #1704.

Risks

  • A burn can still mine after the fail. The text says to finish that burn by hand before any reconcile or move back.

Proof

@linear-code

linear-code Bot commented Oct 10, 2026

Copy link
Copy Markdown

RAI-3128

This was referenced Oct 10, 2026

JuaniRios commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label add-to-gt-merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

⏳ Queued behind 10 other jobs, @JuaniRios. I'll post here when I start.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

🔎 Reviewing 7bb309c, started by @JuaniRios. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes operator guidance only. Before an operator fails a USDC transfer that is stuck before the CCTP burn, the runbook (docs/cli-ops.md) now asks for pending and queued checks on more than one RPC provider, a check for kept sends, and a 0-value self-transfer that closes the nonce, on the burn's chain. The dashboard dialog text and the board copies gate the fail on those steps and point to the runbook. It also covers a burn that mines after the fail and the dropped-burn clear path.

The many earlier review threads are all fixed at this head, and the text now matches what the bot and the CLI do. I found no blocker. Two minor points remain: the late-burn amount the runbook tells operators to copy is in base units, and the Base to Alpaca dialog lost its explicit "do not fail if a burn mined" stop.

A design note for later, not for this PR: all this manual work exists because the rebalance burn records its hash only after the broadcast. Capital burns already persist the signed burn first (ADR 0023, prepare_burn and verify_burn_superseded). If the rebalance burn did the same, fail-usdc-transfer could take a --superseding-tx that the bot checks, and most of these steps would go away. A follow-up issue next to RAI-2630 would track that.

claude-opus-5-5 · high · 14 min

Comment thread docs/cli-ops.md Outdated
Comment thread dashboard/src/lib/transfer.ts Outdated
@JuaniRios
JuaniRios force-pushed the rai-3128-burn-fail-nonce-close branch from 7bb309c to 23d46ff Compare October 11, 2026 02:49
@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@rain-marvin review

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

⏳ Queued behind 16 other jobs, @JuaniRios. I'll post here when I start.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

🔎 Reviewing 23d46ff, started by @JuaniRios. The review will appear here when it's done.

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@rain-marvin review

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

⏳ Queued behind 28 other jobs, @JuaniRios. I'll post here when I start.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes operator guidance only, with no bot code. Before an operator fails a USDC transfer that is stuck before the CCTP burn, the runbook now asks for burn checks on the burn's chain, pending and queued nonce checks on more than one RPC, a check for sends the bot keeps and rebroadcasts, and a self-transfer that closes the nonce, all with the bot stopped. It also covers the recovery of a burn that mines after the fail (mint, deposit, convert). The dashboard and board dialogs now point to those runbook steps for Alpaca to Base, and keep the full text for Base to Alpaca until #1704 adds the withdrawal procedure to the runbook.

Overall read: after 41 resolved threads, the procedure is consistent across the runbook, the dashboard and the board, and the lanes found no new path to stranded or double-spent funds. What is left is three minor gaps in the late-burn recovery (destination-chain kept sends before the offline mint, the unit of the live mint amount, and an expired attestation) and one test nit.

Design note, not blocking: every round of this PR has added another branch to operator prose because the UsdcRebalance burn records its hash only after the broadcast. ADR 0023 already solved this for capital burns (signed burn persisted before broadcast, rebroadcast at startup, and a bot-checked --superseding-tx cancel). A follow-up issue to move the rebalance burn onto that path would remove most of this procedure.

claude-opus-5-5 · high · 1 h 3 min

Comment thread docs/cli-ops.md
Comment thread docs/cli-ops.md Outdated
Comment thread docs/cli-ops.md
Comment thread dashboard/src/lib/transfer.test.ts
@JuaniRios
JuaniRios force-pushed the rai-3128-burn-fail-nonce-close branch from 23d46ff to 151a1b4 Compare October 11, 2026 05:26
@JuaniRios
JuaniRios force-pushed the rai-3128-burn-fail-nonce-close branch from 151a1b4 to 8427df3 Compare October 11, 2026 05:31
@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@rain-marvin review

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

⏳ Queued behind 57 other jobs, @JuaniRios. I'll post here when I start.

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

🔎 Reviewing 8427df3, started by @JuaniRios. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes operator guidance only, with no bot code. Before an operator fails a USDC transfer that is stuck before its burn (WithdrawalComplete or BridgingSubmitting with no recorded burn), the runbook now requires pending and queued checks on more than one RPC provider, a check for kept signed sends, and a self-transfer that closes the nonce, then a fresh burn check. It also gives a recovery for a burn that mines after the fail. The dashboard and Grafana dialogs gate the fail on those runbook steps, and a new test checks that the runbook heading they name still exists.

After 45 resolved threads the procedure is in good shape, and the generated board and guide files match their source. The panel found no blocker. What remains are a few edge cases where two steps disagree:

  • The unknown-nonce fallback in the dropped-burn paragraph closes only the latest nonce. That goes against the resolution of an earlier thread.
  • Step 3 says "start the bot", which conflicts with the stopped-bot rules at WithdrawalComplete and in the Base to Alpaca late-burn recovery.
  • The Base to Alpaca dialog still keeps its own copy of the late-burn steps, and that copy has already drifted from the runbook.

Not raised inline:

  • The runbook section "Withdrawal that never reached the chain" still has no nonce close. That section is outside this diff, the dialog carries the full procedure, and the PR leaves the section to #1704, as already settled in two resolved threads.
  • SPEC.md ("Operator recovery of a pre-burn stranded guard latch") does not mention the nonce close.
  • The root cause is that the rebalance burn records its hash only after the broadcast. Persisting the signed burn before the broadcast, as ADR 0023 already does for capital burns, would replace most of this manual procedure. That belongs in a follow-up, not in this PR.

claude-opus-5-5 · high · 30 min

Comment thread docs/cli-ops.md
Comment thread docs/cli-ops.md
Comment thread dashboard/src/lib/transfer.ts
Comment thread dashboard/src/lib/transfer.ts
Comment thread docs/cli-ops.md
@JuaniRios
JuaniRios marked this pull request as ready for review October 11, 2026 07:51
@rain-marvin

rain-marvin Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

🔎 Reviewing 8427df3, started by @JuaniRios. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes operator guidance only. Before an operator fails a USDC transfer that is stuck before the burn (BridgingSubmitting, or a completed Alpaca withdrawal), the runbook now asks for burn checks on the burn's chain, pending and queued checks on more than one provider, a kept-send check, and a self-transfer that closes the nonce, with a recheck after it. The dashboard and board fail text now gate on those steps, and the runbook also covers a burn that mines after the fail and a dropped burn after clear-pending-burn.

Overall read: the procedure holds up. I checked the new text against the bot code and found no new path where an operator fails a transfer while a burn can still land. The 50 earlier threads are all resolved, and the items deferred to RAI-3196 are not repeated here. Three minor points remain, none blocking: the live vault deposit in the late-burn recovery answers at broadcast, so the reconcile step needs a confirmation gate; complete-mint cannot adopt a relayer mint older than about 33 hours; and the procedure says the bot recorded no burn hash, but the BurnRecordFailed alert gives it.

A design note for a follow-up, not for this PR: the whole procedure makes up by hand for the rebalance burn being broadcast before it is recorded. ADR 0023 already added prepare_burn for capital burns. Moving the UsdcRebalance burn to that pattern would let most of this text shrink to a cancel at a recorded nonce. Also, the fail-gate tests cover only the SPA copy, so plan to move them to the board source before the SPA transfer dialog is retired.

claude-opus-5-5 · high · 43 min

Comment thread docs/cli-ops.md
Comment thread docs/cli-ops.md
Comment thread docs/cli-ops.md

This branch has not been deployed

No deployments
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