Skip to content

[evm, sdk, simplex, indexer]: EntryPoint v0.9 end to end with userOpHash solver selection - #1375

Merged
Wizdave97 merged 12 commits into
mainfrom
roy/entrypoint-v09-end-to-end
Oct 9, 2026
Merged

Wizdave97 merged 12 commits into
mainfrom
roy/entrypoint-v09-end-to-end

Conversation

@royvardhan

@royvardhan royvardhan commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Depends on #1371; until it merges, this diff includes its commits. Closes #816, #1367 and #1368. Part of #1363.

Contracts (#816)

  • The session key signs SelectSolver(bytes32 commitment, bytes32 userOpHash). SolverAccount passes its userOpHash to select during validation, and the gateway keeps the selection in a transient slot keyed by commitment, userOpHash and session key.
  • With solver selection on, fillOrder only succeeds while EntryPoint v0.9 executes the selected UserOperation (getCurrentUserOpHash). It no longer checks msg.sender.
  • Gateway VERSION stays 3 with no storage change, so the upgrade has empty init data. select is now 0x81b06069.

SDK, simplex, indexer (#1367, #1368)

  • SDK 2.9.0: addresses.EntryPoint and getEntryPointAddress replace the v0.8 names. Each bid's EntryPoint comes from its signature and must pair with the gateway's selection format, which the SDK reads on chain, so old and upgraded gateways both work. simulate is one eth_call with selection turned off through a state override. Bundlers other than Pimlico and Alchemy get rundler's priority fee floor. Breaking: getEntryPointV08Address, signSolverSelection and the old SelectOptions are gone (core 2.4.0).
  • simplex 0.17.0 refuses to start, add a chain, swap a bundler or leave watch-only when the bundler does not list the chain's EntryPoint. Limit-order postings record their EntryPoint and are signed again when it changes.
  • The indexer matches v0.9 UserOperationEvents and lists the new testnet SolverAccount next to the old one.

Testnet

Deployed on Chapel and Amoy: SolverAccount 0x7484C6Ff790b898bf7e6960Ffc82f63330445Dc2, gateway implementation 0x38a82f8283a0fAdB763888707aD18fCd34AF719D, and funded paymaster proxies 0x9f4a6F1254f27373C2aca5bDd0e48FbA45EA3aeC (Chapel) and 0x6085a14078B7d26259145a894140f7C8361e02ae (Amoy). The SDK and indexer testnet config point at them.

Before merge, Gargantua sudo must send, for Evm(97) and Evm(80002):

  • intentsCoprocessor.addPaymasterDeployment(chain, proxy), which registers each paymaster
  • intentsCoprocessor.executeOnGateway(chain, upgradeToAndCall(0x38a82f8283a0fAdB763888707aD18fCd34AF719D, "")), which upgrades the gateway

Until the gateway upgrade lands, testnet fills with this branch fail, because the new SolverAccount calls the new select.

Mainnet rollout

  • Ship the SDK and the indexer's SolverAccount list first, then upgrade each chain's gateway and paymaster, then solvers re-delegate. Each chain cuts over hard: old solvers and SDKs cannot fill there once its gateway is upgraded.
  • Polkadot Hub has solver selection on but no EntryPoint v0.9. Turn selection off there or leave it out.
  • Bundlers must serve v0.9. Companion: polytope-labs/hyperfx-orderbook#74 accepts bids signed for either EntryPoint.

Validated: Foundry unit and fork tests, including a real v0.9 handleOps fill, and the SDK, simplex and indexer offline suites. An end-to-end run on an anvil fork of Chapel upgraded the gateway and set the bundler list through the host, ran our rundler, and filled a sponsored v0.9 bid executed by the SDK with userOpHash selection. The indexer picked up its hash, and a bundler off the list was refused.

Follow-ups: Bid.execute reports a reverted bundle only as "Receipt not available yet"; older simplex races remain in reconcile's underfunded write and retire.

@royvardhan
royvardhan marked this pull request as ready for review October 8, 2026 18:00
royvardhan and others added 8 commits October 9, 2026 14:16
Alchemy, the run's RPC provider, does not serve EntryPoint v0.9 as a bundler, so
every scenario timed out without a fill. The workflow now passes
E2E_BSC_TESTNET_BUNDLER_URL and E2E_POLYGON_AMOY_BUNDLER_URL, and the run requires
them instead of defaulting to the RPC URLs.
…ionGas

Pimlico simulates an estimate with paymasterPostOpGasLimit at 2,000,000, which
SimplexPaymaster refuses with InvalidPostOpGasLimit. estimateBidPreVerificationGas
then failed for every sponsored bid, simplex signed the fill estimate's smaller
preVerificationGas, and Pimlico rejected the bid on submission as
"preVerificationGas is not enough".

The estimate now overrides the paymaster's code, as it already does the solver
account's, with a stub that accepts every operation with an empty context.
bidValidUntilBlock converted bidValiditySeconds to blocks with viem's
Chain.blockTime, or 2 seconds for a chain that declares none. BSC Chapel and
Polygon Amoy declare none and BSC declares 0.75s against a real 0.45s, so bids
there reverted FillExpired early: after about 142 of 600 configured seconds on
Chapel.

The block time is now measured over the last 1,000 blocks and reused per chain
for 10 minutes. Where the chain declares a figure the faster of the two is used,
and unreadable blocks fall back to the declared figure, then to 2 seconds.
@Wizdave97
Wizdave97 force-pushed the roy/entrypoint-v09-end-to-end branch from 89c4f2a to 57975ee Compare October 9, 2026 14:18
The bid validity conversion re-measured each chain's block time every 10
minutes. A chain's block time only moves at a hard fork, so each configured
chain is now measured once in the startup warm-up and the figure is kept until
simplex stops. A chain that could not be measured then, or was added later, is
measured at its first bid.
The simplex guides and the example config showed Alchemy's RPC endpoint as each
chain's bundlerUrl. They now use the Hyperbridge bundler at
https://bundler.polytope.technology/<chain>, listed for Ethereum, Base, Arbitrum,
Polygon and BNB Chain in a new Bundler section of the configuration page.
The setup wizard and the operator's Chains panel no longer show a bundler field or
an Alchemy key prefill. Ethereum, Base, Arbitrum, Polygon and BNB Chain are saved
with Hyperbridge's bundler, https://bundler.polytope.technology/<chain>, named in
the chain catalog as hyperbridgeBundlerUrl. The Chains panel writes it over a
different bundler the config held, keeps the config's bundler for a chain outside
the catalog, and will not enable a chain that has neither. simplex init sets it
without asking and only asks on chains with none. Both UIs verify RPC endpoints
only.

bundlerUrl is still required in filler-config.toml and PUT /api/chains, where any
bundler serving the chain's EntryPoint is accepted.
@Wizdave97
Wizdave97 merged commit e90db33 into main Oct 9, 2026
20 of 21 checks passed
@Wizdave97
Wizdave97 deleted the roy/entrypoint-v09-end-to-end branch October 9, 2026 16:43
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.

[evm]: Select UserOpHash instead of solver address in solver selection

2 participants