Skip to content

Fix reentrancy effort-limit bypass in FlowTransactionScheduler - #618

Merged
janezpodhostnik merged 4 commits into
masterfrom
fix/scheduler-reentrancy-public
Aug 4, 2026
Merged

Fix reentrancy effort-limit bypass in FlowTransactionScheduler#618
janezpodhostnik merged 4 commits into
masterfrom
fix/scheduler-reentrancy-public

Conversation

@janezpodhostnik

Copy link
Copy Markdown
Collaborator

Fix a reentrancy vector in schedule() where slot capacity was only reserved
after the handler callback ran. A handler's resolveView() could reenter
schedule() and fit additional transactions into a slot whose capacity was
already spoken for, bypassing the per-priority effort limit.

This ports the fix already deployed via onflow/flow-core-contracts-internal#7.

Changes

  • Reserve slot capacity (addTransaction) before invoking the handler callback
    in schedule(), following checks-effects-interactions
  • Add a defensive assertion in addTransaction() that the per-priority slot
    total never exceeds the configured effort limit
  • Add a reentrancy reproducer test (testScheduleReentrancy) with a test-only
    ReentrantHandler that attempts to nest a schedule() call; verified to
    fail against the pre-fix contract

Related: onflow/flow-core-contracts-internal#7

Address review feedback: extract self.config.priorityEffortLimit[txData.priority]!
into a local variable used by both the assert condition and its message.

make generate for the embedded contract assets.
Adds a test-only ReentrantHandler whose resolveView() attempts to reenter
schedule() while the outer schedule() call is still in flight, trying to
stuff two 9000-effort high-priority transactions into a 15000-effort slot.

With the checks-effects-interactions fix, the outer call reserves its slot
capacity before the handler callback runs, so the nested schedule fails the
effort estimate and the whole transaction is rolled back atomically.
Verified that this test fails against the pre-fix contract.

- test-only ReentrantHandler in TestFlowScheduledTransactionHandler
- schedule_transaction_reentrant.cdc test transaction
- testScheduleReentrancy asserting failure and full slot rollback
- make generate for the embedded assets
@janezpodhostnik janezpodhostnik self-assigned this Aug 4, 2026
@janezpodhostnik
janezpodhostnik merged commit 6339190 into master Aug 4, 2026
2 checks passed
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.

2 participants