Skip to content

docs(evm): add nonce lanes guide for concurrent submission from one account - #75

Open
alexander-sei wants to merge 5 commits into
mainfrom
docs/hft-parallel-nonce-submission
Open

docs(evm): add nonce lanes guide for concurrent submission from one account#75
alexander-sei wants to merge 5 commits into
mainfrom
docs/hft-parallel-nonce-submission

Conversation

@alexander-sei

@alexander-sei alexander-sei commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

What is the purpose of the change?

Add new content: a guide and tutorial for sei-nonce-lanes, for teams that need many independent transactions in flight from one funded Sei address.

Previously opened as "Parallel Nonce Submission for High-Frequency Trading." Both halves of that title were wrong, so the page has been retitled and reframed — see Renamed and corrected below.

Describe the changes to the documentation

Target audience: anyone who needs one funded address to do many things that do not depend on each other and currently works around Sei's sequential nonce model with a fleet of hot wallets. Market making and order flow, but also liquidation and keeper bots, oracle updates, payout and claim batching, and game backends.

New page evm/nonce-lanes.mdx, added to the existing Ecosystem Tutorials group in the EVM tab:

  • Why one account is one queue — sequential nonces, revert vs. never-landed, and the two Sei-specific facts that sharpen it (strict nonce admission under Giga; no dependable pending view), linked to the finality and technical-reference pages.
  • How it works — one subsection per mechanism, each with a diagram: ERC-4337 two-dimensional nonce lanes, EIP-7702 delegation, gas-only relayers fed by an in-process bundling queue, the bundle lifecycle, and failure isolation.
  • Why this is hard to replicate — a comparison table against a single wallet, a wallet fleet, and a public ERC-4337 bundler, plus the structural reasons, and the caveat that submission concurrency is not execution parallelism.
  • Tutorial<Steps> from clone and verify through status → delegate → fund → submit, with <Tabs> for a local Anvil Prague fork vs. Atlantic-2, an annotated report, and optional real-swap and baseline runs.
  • Tuning, a condensed configuration reference, guidance for pointing it at your own contract with a buildOp snippet, the production-readiness list, troubleshooting, and resources.

Supporting changes:

  • snippets/nonce-lane-diagrams.jsx — six theme-aware SVG diagrams following the existing Giga diagram convention (currentColor ink, --sei-maroon-50 accent).
  • docs.json — one line, adding the page to Ecosystem Tutorials.
  • evm/index.mdx — a card in Use Cases.
  • .github/styles/Sei/Headings.yml — one line, adding ERC to the exceptions list (see Notes).

Renamed and corrected

Reviewers of the first version should know what changed and why.

The title over-promised and under-served. "Parallel nonce" names a mechanism that does not exist — EVM nonces are never parallel; the feature is ERC-4337's two-dimensional nonce. In Sei's docs "parallel" also reads as parallel execution, so the old title created an association the page then needed a <Warning> to undo. "HFT" over-claimed (the reference implementation has no strategy engine, market data, or order book) while excluding the keepers, liquidators, and batchers the pattern serves equally well.

A load-bearing factual claim was wrong. The page stated that eth_getTransactionCount(address, "pending") returns the same value as "latest". evm/reference documents the opposite: the pending tag returns EvmNextPendingNonce from the mempool. The supportable claim is the one in evm/evm-parity/finality — a pending nonce differing from the confirmed nonce is unreliable. Reworded, not restructured: the design argument holds either way, because its hot path reads no nonces at all.

The comparison table overstated the result. It set LANE_POOL_SIZE "up to 4096" against a wallet fleet's N, which compares signed-and-unresolved operations against concurrent transactions. Those are now separate rows, broadcast width is stated as RELAYER_COUNT, and the text says plainly that a wallet fleet can match the width — what it cannot match is doing so from one balance, one approval set, and one key.

"Private mempool" named a component that does not exist. A mempool is a shared admission buffer: transactions arrive from strangers, are gossiped, and wait for whichever producer or bundler picks them up. The reference implementation has none of that — its queue is an in-process array, filled only by the process that signed the operations and gone when that process exits. The old name sent readers looking for gossip, admission policy, and eviction, and it was especially confusing on a page where "mempool" otherwise means Autobahn's producer mempool two sections earlier. It is now a bundling queue, which says what it does: hold signed UserOperations and pack them into lane-safe handleOps bundles. The paragraph explaining the ERC-7562 exemption now leads with why the component is not a mempool, since that is exactly what earns the exemption — an in-process queue never enters the alt-mempool, so SAME_SENDER_MEMPOOL_COUNT never applies. The upstream repository made the matching rename (PrivateMempoolBundlingQueue, mempool.tsbundling-queue.ts), so the buildOp snippet now reads bundlingQueue.add(...). Every remaining "mempool" on the page refers to a real one.

Navigation. The first version added a top-level High-Frequency Trading group holding one page, which put a niche topic ahead of the core sei-js group. The page now sits in Ecosystem Tutorials alongside the other standalone tutorials, which is also where the account-abstraction pages live.

Smaller fixes: retitled "The moat" (AGENTS.md asks for no investment framing); attributed the mempool to Autobahn under Giga mode to match node/technical-reference; replaced the hard-coded 400 ms figure with pointers to Twin-Turbo and Giga, since sei-giga-specs warns against mixing current and Giga numbers; cross-linked Pimlico and Thirdweb EIP-7702 with guidance on when a hosted bundler is the better choice; fixed two British spellings that _typos.toml would not catch because it sets no locale.

Notes

  • mint broken-links and mint validate both pass. Vale and typos report 0 errors and 0 warnings. The Sei.Headings warning noted earlier on "ERC-4337 nonce lanes" is fixed here rather than deferred: the rule flagged any heading containing ERC-<digits> because ERC was missing from the exceptions list, which also affected several existing pages. That is a one-line change to .github/styles/Sei/Headings.yml; say the word if you would rather it were a separate PR.
  • No redirects needed (new page, nothing moved in main). llms.txt is left to the scheduled regeneration workflow.
  • Throughput figures in Tuning are quoted as dated measurements (Atlantic-2, September 3, 2026) for one call shape, not protocol limits.

Add a High-Frequency Trading group to the EVM tab with a guide to
sei-protocol/sei-parallel-nonce-hft: how EIP-7702 delegation, ERC-4337
nonce lanes, a private mempool, and gas-only relayers let one funded
address submit many independent operations without a sequential nonce
queue.

- Explain the problem (sequential nonces, no pending state on Sei, strict
  nonce admission under Giga) and each mechanism with its own diagram
- Add a "moat" section comparing the design with single wallets, wallet
  fleets, and public ERC-4337 bundlers
- Step-by-step tutorial for a local Prague fork and Atlantic-2, an
  annotated example report, tuning notes, a configuration reference,
  venue-integration guidance, and troubleshooting
- Six theme-aware SVG diagrams in snippets/parallel-nonce-diagrams.jsx,
  following the existing Giga diagram convention
- Link the page from the EVM home page Use Cases

Co-authored-by: Cursor <cursoragent@cursor.com>
@mintlify

mintlify Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
sei-docs 🟢 Ready View Preview Sep 11, 2026, 3:21 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

…check

The spelling check treats the "Pn"/"pn" prefix as a misspelling of
"on". Rename the snippet components to a ParallelNonce* prefix, matching
the Giga* diagram convention, and give SVG marker ids descriptive names.

Co-authored-by: Cursor <cursoragent@cursor.com>
…laim

The page promised parallelism it does not deliver and narrowed its audience
to one industry. "Parallel nonce" names a mechanism that does not exist:
EVM nonces are never parallel, and the actual feature is ERC-4337's
two-dimensional nonce. Inside Sei's docs "parallel" also reads as parallel
execution, which is why the page previously needed a warning to undo the
association its own title created. Retitle to "Nonce Lanes", lead with
submission concurrency, and name the other audiences this serves (keepers,
liquidators, oracle updaters, payout batchers) rather than HFT alone.

Correct the load-bearing factual claim. The page asserted that
`eth_getTransactionCount(address, "pending")` returns the same value as
`"latest"`. evm/reference documents the opposite: the pending tag returns
EvmNextPendingNonce from the mempool. The supportable claim is the one in
evm/evm-parity/finality, that a pending nonce differing from the confirmed
nonce is unreliable. The design argument is unaffected, since a hot path
that reads no nonces is the right answer either way, so this is a rewording
rather than a restructure.

Fix the comparison table, which overstated the result. It put
`LANE_POOL_SIZE` "up to 4096" against a wallet fleet's N, comparing signed
unresolved operations against concurrent transactions. Split those into
separate rows, state that broadcast width is `RELAYER_COUNT`, and say
plainly that a wallet fleet can match the width -- what it cannot match is
doing so from one balance, one approval set, and one key.

Also:

- Move the page from a new top-level "High-Frequency Trading" group into the
  existing "Ecosystem Tutorials" group, next to the other standalone
  tutorials. A dedicated top-level group for one page put a niche topic
  ahead of the core SDK group in reading order
- Retitle "The moat" to "Why this is hard to replicate"; AGENTS.md asks for
  no investment framing
- Attribute the mempool to Autobahn under Giga mode, matching
  node/technical-reference and evm/reference
- Drop the hard-coded 400 ms figure in favor of a pointer to Twin-Turbo and
  Giga, since sei-giga-specs warns against mixing current and Giga numbers
- Cross-link Pimlico and Thirdweb EIP-7702, and say when to prefer a hosted
  bundler; those were the only other 4337/7702 pages and went unlinked
- Track the repository's renames: sei-nonce-lanes, `npm run submit`,
  `REVERT_ORDER_INDEX`, and Node 22 rather than 26
- Fix "neighbours"/"neighbouring"; the repo is American English in prose and
  _typos.toml sets no locale, so CI would not have caught it
- Rename the snippet to nonce-lane-diagrams.jsx with matching components

mint broken-links and mint validate both pass. Vale reports no errors; the
one remaining Sei.Headings warning fires on any heading containing
"ERC-<digits>" because ERC is absent from the exceptions list in
.github/styles/Sei/Headings.yml, which also affects existing pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexander-sei alexander-sei changed the title docs(evm): add parallel nonce submission tutorial for HFT traders docs(evm): add nonce lanes guide for concurrent submission from one account Sep 11, 2026
alexander-sei and others added 2 commits September 11, 2026 17:19
Sei.Headings flagged any heading containing a hyphenated ERC standard even
when the heading was already correct sentence case, because ERC was missing
from the exceptions list while EVM, NFT, RPC, and the other acronyms were
present. "ERC-4337 nonce lanes" tripped it, as did "NFT and ERC-1155" and the
"ERC-20 Interaction" headings on the existing evm-parity example pages.

Add ERC alongside EVM. Repo-wide this clears seven warnings and introduces
none (1213 -> 1206). It does not hide genuine sentence-case violations: the
check already tolerates a single stray capitalized word, so headings like
"EVM Interaction" never warned in the first place, and every remaining ERC
heading still warns because it has an independent title-case problem.

Co-authored-by: Cursor <cursoragent@cursor.com>
A mempool is a shared admission buffer: transactions arrive from strangers,
are gossiped, and wait for whichever producer or bundler picks them up.
sei-nonce-lanes has none of that. Its queue is an in-process array, filled
only by the process that signed the operations and gone when that process
exits. Calling it a "private mempool" sent readers looking for gossip,
admission policy, and eviction that do not exist, and it was especially
confusing on a Sei page where "mempool" otherwise means the Autobahn
producer mempool two sections earlier.

Rename it to "bundling queue" throughout, which says what it does: hold
signed UserOperations and pack them into lane-safe handleOps bundles. The
paragraph that explains the ERC-7562 exemption now leads with why the
component is not a mempool, since that is precisely what earns the
exemption -- an in-process queue never enters the alt-mempool, so
SAME_SENDER_MEMPOOL_COUNT never applies to it.

- Retitle the pipeline diagram box and update its aria-label
- "take bundle from the mempool" -> "from the queue" in the bundle
  lifecycle diagram
- Rename the `mempool.add(...)` call in the integration snippet to
  `bundlingQueue.add(...)`, tracking the repository rename of
  PrivateMempool to BundlingQueue and mempool.ts to bundling-queue.ts

The remaining "mempool" mentions on the page are deliberate and refer to
real mempools: Autobahn's strict nonce admission, the pending-nonce
warning, and the canonical ERC-4337 alt-mempool this design bypasses.

Vale and typos both report no errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Sep 11, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Documentation and navigation only; no runtime or contract changes in this repo.

Overview
Adds a new Ecosystem Tutorials page at /evm/nonce-lanes that documents sei-nonce-lanes: concurrent transaction submission from one funded Sei address using ERC-4337 lane nonces, EIP-7702 delegation, an in-process bundling queue, and gas-only relayers—with Sei-specific context (strict nonce admission, unreliable pending nonce) and a full tutorial (delegatefundsubmit).

Supporting updates wire the page into docs.json navigation and an EVM home Use Cases card; snippets/nonce-lane-diagrams.jsx adds six theme-aware SVG diagrams imported by the guide. Headings.yml gains ERC as a sentence-case exception for headings like “ERC-4337 nonce lanes.”

Reviewed by Cursor Bugbot for commit b1ce183. Bugbot is set up for automated code reviews on this repo. Configure here.

@seidroid seidroid 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.

A well-structured, unusually thorough new EVM guide whose internal links, snippet conventions, and cited facts I verified against the repo — but one diagram still carries the exact eth_getTransactionCount(..., "pending") == "latest" claim the prose was rewritten to correct, and the tutorial's first step clones a repository the author states is still private.

Findings: 2 blocking | 8 non-blocking | 6 posted inline

Blockers

  • Tutorial depends on a private repository (Codex P1). sei-protocol/sei-nonce-lanes is referenced from the intro (evm/nonce-lanes.mdx:12), the clone step (:205), the configuration reference, and a resource card. The PR description states the repo is private and asks that this not merge until it is public — until then the first tutorial step fails for every public reader and four links 404. I could not independently confirm current visibility (no network access from this environment), so please verify before merging.
  • 1 blocking issue(s) flagged inline on specific lines.

Non-blocking

  • The Cursor second-opinion pass produced no outputcursor-review.md is empty, so that review lane contributed nothing. REVIEW_GUIDELINES.md is also empty; I applied AGENTS.md and STYLE_GUIDE.md conventions instead.
  • Verified clean: every internal link target resolves — /evm/evm-parity/finality#pending-state, /evm/evm-parity/transaction-types#set-code-eip-7702-auth-list-requirement, /node/technical-reference#giga-mode-behavior-and-per-block-limits (h4 at node/technical-reference.mdx:226), plus /evm/networks, /learn/rpc-providers, /learn/twin-turbo-consensus, /learn/sei-giga, /evm/best-practices/optimizing-for-parallelization, /evm/wallet-integrations/{pimlico,thirdweb-7702}. The txpool_content truncation claim matches evm/reference.mdx:1122, the EntryPoint v0.8 address and chain IDs are correct, and the snippet follows the giga-diagrams.jsx convention (currentColor ink, --sei-maroon-50/--sei-gold-25, both defined in style.css).
  • Bundling a shared lint-config change with content. .github/styles/Sei/Headings.yml is repo-wide and affects existing pages' annotations. The author already offered to split it; given it only changes advisory annotations (prose-style.yml sets fail_on_error: false), keeping it here is fine, but splitting would make the content diff cleanly revertable.
  • 5 suggestion(s)/nit(s) flagged inline on specific lines.

);
})}
<text x={40} y={124} fontSize="10.5" fill={ink} fillOpacity="0.7">nonces 7 and 8 are signed and valid, but nothing at or above 7 can execute until 6 is filled or replaced</text>
<text x={40} y={142} fontSize="10.5" fill={ink} fillOpacity="0.7">on Sei there is no pending view to inspect: eth_getTransactionCount(addr, "pending") equals "latest", and a nonce gap is rejected with a bad nonce error</text>

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.

[blocker] This diagram still carries the claim the PR was specifically rewritten to remove. It says eth_getTransactionCount(addr, "pending") equals "latest", which contradicts:

  • this page's own <Warning>: "it is not an alias for "latest""
  • evm/reference.mdx:345: "For the 'pending' tag Sei returns EvmNextPendingNonce from the CometBFT mempool"

A reader who trusts the diagram gets the opposite mental model from the paragraph directly above it.

Second issue on the same line: "a nonce gap is rejected with a bad nonce error" is stated unconditionally, while the prose correctly scopes it to Giga ("Under Giga, the Autobahn producer mempool ... rejects a gap with a bad nonce error").

Suggested rewording that matches both the prose and evm/reference.mdx:

on Sei the pending view is not dependable: eth_getTransactionCount(addr, "pending") varies by node, and under Giga a nonce gap is rejected with a bad nonce error

</defs>

<rect x={40} y={40} width={330} height={216} rx={9} {...box} stroke={accent} strokeOpacity="0.9" strokeWidth="1.3" />
<text x={205} y={64} fontSize="13" fontWeight="600" textAnchor="middle" fill={ink}>Trading EOA, same address</text>

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.

[suggestion] The retitling deliberately moved the page off trading-specific framing ("market making and order flow, but also liquidation and keeper bots, oracle updates, payout and claim batching, and game backends"), and the prose consistently says funded account / funded EOA. The diagrams didn't follow: "Trading EOA" (:152, :211), "the trading EOA" (:141, :181, :248), "chosen by the trader" (:89), "the trader's signature" (:251), and "inventory" (:47, :51, :54, :207, :237).

The TRADER_PRIVATE_KEY env var is upstream and should stay, but the diagram labels are yours — "Funded EOA" and "funds"/"assets" would match the reframing and cost nothing.

- Sei Network
- SeiDB
- EVM
- ERC

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.

[suggestion] If ERC needs the exception, EIP almost certainly does too — the $sentence check lowercases non-exception words, so EIP-7702 gets the same treatment as ERC-4337 even in first position. This page has ### EIP-7702 keeps the funded address (evm/nonce-lanes.mdx:80), and existing pages have several mid-heading cases (evm/evm-parity/gas-and-fees.mdx:36, evm/evm-parity/signing.mdx:53, evm/evm-parity/transaction-types.mdx:19, evm/wallet-integrations/thirdweb-7702.mdx:28).

Since filter_mode: added means only changed lines are annotated, line 80 of this PR is exactly the kind of hit this would surface. Worth adding EIP in the same one-line spirit.

Comment thread evm/nonce-lanes.mdx
</Warning>

<Note>
Block time and gas limits differ between today's [Twin-Turbo consensus](/learn/twin-turbo-consensus) and [Sei Giga](/learn/sei-giga). Size a relayer pool against the network you are actually submitting to, and measure rather than assuming.

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.

[nit] AGENTS.md lists Twin Turbo Consensus as a proper noun, and the rest of the repo writes it unhyphenated (learn/sei-giga.mdx:99, :196-197). Suggest "Twin Turbo consensus" to match.

Comment thread evm/nonce-lanes.mdx
<Accordion title="Bundle width: gas efficiency against isolation">
`MAX_OPS_PER_BUNDLE` trades amortized outer-transaction overhead for the size of the shared validation failure domain. A width of `1` gives maximum isolation and the highest overhead. Execution reverts stay per-operation at any width. The relayer caps signed transaction gas below the live block gas limit and rejects a bundle whose estimate cannot fit.

As a reference point, on Atlantic-2 on September 3, 2026, the real-swap path sustained 77 operations per bundle; 78 hit the 12,500,000 block-gas ceiling and failed safely during simulation. Width 76 produced the best observed submission rate for that call shape, 47.7 landed swaps per second. Treat these as measurements for one call shape on one network at one point in time, not as protocol limits.

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.

[nit] AGENTS.md says to "link to live status/dashboards rather than hard-coding network stats that change"12,500,000 is a block gas limit and will drift, especially across the Twin Turbo → Giga transition this page already warns about two sections up.

The closing caveat ("measurements for one call shape on one network at one point in time, not as protocol limits") does most of the work, so this is a nit rather than a fix-now. Consider dropping just the absolute gas figure and keeping the relative result (77 fits, 78 does not), which is the part that stays true longer.

<line x1={30} y1={222} x2={870} y2={222} stroke={ink} strokeOpacity="0.15" strokeWidth="1" />
<rect x={30} y={236} width={840} height={58} rx={9} fill={warn} fillOpacity="0.08" stroke={warn} strokeOpacity="0.8" strokeWidth="1" />
<text x={48} y={258} fontSize="11.5" fontWeight="600" fill={ink}>Never submitted: nothing consumed</text>
<text x={48} y={278} fontSize="10" fill={ink} fillOpacity="0.8">a signed operation whose outer transaction was dropped, evicted, or never broadcast leaves its lane sequence untouched; neighbouring lanes stay valid and the journal requeues it</text>

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.

[nit] neighbouringneighboring. The PR description notes two British spellings were fixed in the MDX; this one in the snippet was missed, and _typos.toml won't catch it since it sets no locale.

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