Skip to content

Drop checks-effects-interactions: re-entry cannot happen on Solana - #244

Merged
mikemaccana merged 2 commits into
mainfrom
claude/affectionate-turing-4owvhb
Oct 4, 2026
Merged

mikemaccana merged 2 commits into
mainfrom
claude/affectionate-turing-4owvhb

Conversation

@mikemaccana

@mikemaccana mikemaccana commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

The book taught checks-effects-interactions as protection against a token hook, or an upgraded callee, re-entering a program mid-transfer and double-withdrawing. On Solana that call can't happen. solana-program-runtime returns InstructionError::ReentrancyNotAllowed when a program already on the call stack is invoked by anything other than itself. A failed call also undoes the whole transaction. So the order in which a handler writes its own state and calls other programs doesn't open an attack.

This follows quicknode/solana-program-examples#189, which removes the same claim from the companion programs' comments and READMEs.

After this merges, the book's prose, glossary and figures no longer mention checks-effects-interactions. The only remaining mentions are the example sentences in the comment on the lint rule in scripts/lint-manuscript.mjs, which quote the old wording to show what the rule rejects.

Changes

  • The Adversary: the paragraph that taught the rule now states the runtime's re-entry rule and the transaction's atomicity, then introduces the three boundary checks that do matter (validate what a CPI returns, re-read what a CPI changed, assume the instructions after yours are hostile). "follow the same rule" → "do this". In the checklist, "Apply checks-effects-interactions at every boundary" → "Make every invariant hold at the end of your own instruction".
  • Order Book: the settle_funds() paragraph says what the handler does: it zeroes the counters and pays out the snapshot, so a user who calls settle_funds() again is paid nothing, and a failed transfer undoes the zeroing. The summary bullet says the same.
  • Fundraiser: removed the checks-effects-interactions sentence. The double-refund explanation (the receipt is closed) stays.
  • Managed Fund: removed the "(checks-effects-interactions, as in every chapter)" aside.
  • Betting Market: "Two orderings in this handler close attacks", with its re-entry bullet, is now one paragraph: the claim removes the bet from the index and closes the account, and the closed account stops a double claim (test_double_claim_fails).
  • Options: "Then the effects come before the transfer" → "Then, before the transfer, the handler makes these changes in order".
  • Perpetual Futures: removed checks-effects-interactions from the summary's list of concepts already covered.
  • Glossary: removed the checks-effects-interactions entry. Nothing linked to it.
  • Figures: in order-book-settle.svg, the caption "checks-effects-interactions, so a re-entrant caller finds nothing left" → "the handler zeroes the counters and pays out what they held, so a user who settles again is paid nothing". In betting-alice-claim.svg, removed the "effects before interactions" label and "first" from "1. index entry removed first".

Checks

npm run lint, node scripts/check-figure-geometry.mjs and npm run build-pdf pass. Both changed figures were rendered and checked by eye.

This branch was reset to main after #243 merged. A commit had been pushed to it after that merge, and it now sits on top of main here.

🤖 Generated with Claude Code

https://claude.ai/code/session_014pXG1pw56BE99p4A8qmrQk

Mike MacCana added 2 commits October 4, 2026 16:54
The book taught checks-effects-interactions as protection against a
token hook or an upgraded callee re-entering a program mid-transfer.
Solana's runtime rejects that call with ReentrancyNotAllowed, and a
failed call undoes the whole transaction, so the order in which a handler
writes its own state and calls other programs opens no attack.

The Adversary chapter now states the runtime rule. The order book,
fundraiser, managed fund, betting market, options and perpetual futures
chapters describe what their handlers do without the label, and the
glossary entry is gone. Follows quicknode/solana-program-examples#189,
which removes the same claim from the programs' comments.

Claude-Session: https://claude.ai/code/session_014pXG1pw56BE99p4A8qmrQk
The order book settlement figure said the ordering means "a re-entrant
caller finds nothing left", and the betting claim figure labelled its
first step "effects before interactions". Neither applies on Solana.
The settlement caption now says what the handler does; the claim figure
drops the label.

Claude-Session: https://claude.ai/code/session_014pXG1pw56BE99p4A8qmrQk
@mikemaccana
mikemaccana merged commit a576bb5 into main Oct 4, 2026
1 check passed
@mikemaccana
mikemaccana deleted the claude/affectionate-turing-4owvhb branch October 13, 2026 00:23
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