Skip to content

Check the proposer payment on both the regular and merged paths - #534

Open
0w3n-d wants to merge 1 commit into
od/builder-sim-execute-step4from
od/builder-sim-payment-step5
Open

Check the proposer payment on both the regular and merged paths#534
0w3n-d wants to merge 1 commit into
od/builder-sim-execute-step4from
od/builder-sim-payment-step5

Conversation

@0w3n-d

@0w3n-d 0w3n-d commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Issue: #527 (step 5 of 10)

Base branch: od/builder-sim-execute-step4 (#532, step 4). Retarget as the
stack merges.

What this PR does

validate now checks the proposer was paid, and validate_merged adds the
relay-internal merged path.

The recipient's whole-block balance delta decides first. It falls short only
when the proposer also spends in the block, and then the payment must be
recognisable in the last transaction: a direct transfer, or a
PAYMENT_FORWARDER call where that runtime is actually deployed. Merged blocks
sum two positions, the base block's payment transaction at
base_payment_tx_index and the appended distribution transaction.

helix-common moves from a dev-dependency to a real one, for the payment
constants and the shared multisend_paid_amount. That settles the issue's open
question about when the builder takes that dependency.

What this PR deliberately does not do

This ports the reth behavior unchanged, including the multiSend weakness in
#533: a payment is credited from calldata rather than from effect. Porting it
as-is keeps both simulators agreeing on what counts as a payment, so no merged
block is accepted by one relay simulator and rejected by another. #533 fixes
both at once in helix-common.

No test asserts that a fake multiSend is accepted, so nothing here has to be
un-asserted when #533 lands.

One check reth performs is absent: comparing every payment transaction's chain
id. validate_block_pre_execution already rejects a wrong chain id for every
transaction in the block. What survives is the case ethrex exempts — a legacy
transaction carrying no chain id at all — which the payment path still rejects.

Tests

Written first and signed off before implementation. 12 new, 32 in the file:

  • A balance delta covering the bid is accepted with no payment transaction.
  • A trailing direct transfer is accepted when the delta falls short.
  • Underpayment by one wei, a payment that tips the builder, and an unprotected
    pre-EIP-155 payment are each rejected.
  • A withdrawal does not pay the bid: it is consensus-layer income, so it counts
    against the rise rather than towards it.
  • A forwarder payment is accepted where the runtime is deployed and rejected
    where it is absent, since a value call to a codeless address succeeds and
    keeps the value. The genesis deploys the real 20-byte runtime from
    contracts/README.md, so this executes rather than mocks.
  • A reverted payment is rejected, driven by the forwarder's own timestamp check.
  • A merged payment split across two positions is accepted; a wrong base index
    fails closed; the same block fails on the regular path, which pins the
    difference between the two entry points.

The fixture's proposer is now a funded signer so it can spend. Without that the
balance delta covers every case and the fallback is never exercised.

just fmt-check, just test and cargo clippy --all-features --no-deps -- -D warnings
are clean. 66 tests pass in helix-builder, up from 54.

Reviewer checklist

  • CI (lint, unit-test) is green
  • Matches the linked issue/step
  • No unexplained scope creep or unrelated files touched

The recipient's whole-block balance delta decides first. When the
proposer also spends, the payment must be recognisable: a direct
transfer, or a PAYMENT_FORWARDER call where its runtime is deployed.
Merged blocks sum the base payment tx and the trailing distribution tx.

helix-common becomes a runtime dependency for the payment constants.

Ports the current reth behavior unchanged, including the multiSend gap
that #533 will close for both simulators at once.

Step 5 of #527.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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