Base and Robinhood Chain side by side: what a trading bot must change
Both chains are EVM L2s that pay gas in ETH, so a Base bot compiles and connects to Robinhood Chain on the first try. Then fees, ordering, confirmation and the early-data stream all behave differently. A row-by-row map of what to rewrite, with live answers from both chains.
Endpoints and plans for the networks in this post: Base RPC endpoint · Robinhood Chain RPC endpoint.
A team that already executes on Base and adds Robinhood Chain usually starts by copying the Base config, changing the chain ID from 8453 to 4663 and pointing at a new URL. Everything connects. eth_call, eth_getLogs and eth_sendRawTransaction behave as before, both chains pay gas in ETH, and both describe themselves as layer-2 chains on Ethereum. The differences sit in the parts a trading bot leans on hardest: how a transaction gets its position in a block, how the bot decides a fill is settled, and what the early-data stream actually delivers.
We sent the same five-call batch to both chains through Triport on 2026-10-13 at 17:37 UTC. Base answered eth_maxPriorityFeePerGas with 0xf4240 (1,000,000 wei); Robinhood Chain answered 0x0. Base returned a safe block 31 blocks behind its head and a finalized block 530 blocks behind it. Those two answers already describe most of this post: on Base the tip still buys a position, and protocol tags tell you how settled a block is; on Robinhood Chain neither is the tool to reach for.
The two chains in one table
The "Base" and "Robinhood Chain" columns combine each chain's official documentation, read on 2026-10-13, with the status of each surface in Triport's capability registry on the same day. "Triport" rows describe our contract, not the chain.
| Row | Base | Robinhood Chain |
|---|---|---|
| Stack | Ethereum rollup from the OP Stack line (its upgrade history lists the Optimism Isthmus and Jovian hardforks), Reth-based execution, one active sequencer | Arbitrum Nitro L2 built on Arbitrum Dedicated Blockchains; a sequencer orders every transaction |
| Ordering | By priority fee and arrival time; fee decides which Flashblock a transaction lands in | First-come, first-served by sequencer arrival; "Priority gas auctions do not exist here" |
| Early stream on Triport | Flashblocks feed, /ws/base-feed, Pro and up, address filter required, events marked preconfirmed | Sequencer feed, /ws/robinhood-feed, Pro and up, assembled L2 blocks, resume with from_sequence |
| Block tags on Triport | latest, earliest, pending, safe, finalized; selectors are passed through unchanged | latest, earliest, pending; safe and finalized are not part of the contract |
| Finality (official) | Flashblock, L2 block (about 2 seconds), L1 batch (about 2 minutes), L1 finality (about 20 minutes) | Soft confirmation, posted to Ethereum (minutes), Ethereum finality about 13 minutes after posting |
| Canonical withdrawal to Ethereum | 5 days, or 1 day on the dual-proof path | 7-day challenge period |
| Traces on Triport | debug_traceTransaction, debug_traceBlockByNumber, Pro and up | Four debug_* methods, best-effort, no availability SLA, all plans |
| Conditional send on Triport | Not part of Triport's Base contract today | eth_sendRawTransactionConditional published |
| WebSocket on Triport | newHeads on /ws/base, Basic and up; events via eth_getLogs or the Flashblocks feed | newHeads and logs, Basic and up |
The rest of the post takes the rows that force code changes, in the order a bot meets them.
Ordering and fees: delete the tip ladder, keep the estimator
Base's transaction-ordering specification says transactions "are ordered based priority fee and arrival time, which determines which Flashblock they are included in", and that "later-arriving transactions with higher priority fees cannot be included in earlier Flashblocks". A Base block is built in Flashblocks, and the gas schedule in the same spec opens the first Flashblock with a tenth of the block gas limit and the tenth with the full limit. Within each Flashblock the tip still sorts transactions, so a Base bot that bids a priority fee is doing something real. Our priority-fee comparison covers how that bid is usually priced.
Robinhood Chain's differences page is blunt: the sequencer works "first-come, first-served", "Priority gas auctions do not exist here; consequently, increasing your fee will not shift your transaction ahead of others already in the queue." The 0x0 we read from eth_maxPriorityFeePerGas is the node agreeing with the documentation.
What to change:
- Remove replacement-with-higher-tip loops and gas-price ladders on the Robinhood Chain path. They add cost and change nothing.
- Keep
eth_estimateGasand the base fee. Robinhood Chain fees are L2 execution gas plus an L1 data component, so a limit hard-coded from a Base run can be wrong in both directions. - Move the competitive effort to submission: on a first-come, first-served chain, the order in which your signed transaction reaches the sequencer is what counts, and that is a property of your own pipeline, not of a fee field.
Early data: Flashblocks deltas are not sequencer-feed blocks
Both chains offer something earlier than a sealed block over a polled RPC call, and both are behind the same Pro tier on Triport. They are not the same object.
The Base Flashblocks feed on Triport carries normalized deltas of the block being built: each message has an opaque payload_id, an index, a diff with the transactions added since the previous delta, and a finality of preconfirmed. Index 0 anchors a block, deltas must be contiguous, and a consumer has to reconcile against the canonical block before treating anything as final. The stream requires an address filter, passed as a JSON query value.
The Robinhood Chain sequencer feed carries already assembled L2 blocks. Each frame has a sequenceNumber that equals the L2 block number, the stream keeps a bounded replay window (at most 8,192 frames, 64 MiB or five minutes), and a client that drops can reconnect with ?from_sequence= and read resume.bufferComplete to learn whether the window still covered its cursor. There is no address filter; you filter on your side.
So the subscriber is a rewrite, in three places:
Base Flashblocks feed Robinhood Chain sequencer feed
--------------------------------------- ---------------------------------------
key: (payload_id, index) key: sequenceNumber (= L2 block number)
unit: delta inside a block unit: whole L2 block
filter: server side, address required filter: client side
gap handling: anchor on index 0, gap handling: reconnect with
reconcile with the canonical block ?from_sequence=<last seen + 1>;
if bufferComplete is false,
backfill the gap over RPCA shared "on new transactions" handler can stay; the adapter in front of it cannot. Keep two adapters behind one internal event shape, and test the Robinhood Chain gap path explicitly by killing the socket for longer than the replay window.
Confirmation: tags on Base, depth on Robinhood Chain
On Base, our contract passes block selectors through unchanged, and the chain reports three heads. In our capture latest was block 52,561,854, safe 52,561,823 and finalized 52,561,324. Our unsafe, safe and finalized guide explains what each one guarantees; a Base bot that waits for safe before releasing collateral is using the protocol as designed.
On Robinhood Chain, the eth_call parameter table lists latest, earliest and pending (plus hex numbers); safe and finalized are not part of Triport's contract. The official finality page describes three stages instead: a soft confirmation from the sequencer, the batch posted to Ethereum within minutes, and Ethereum finality about 13 minutes after posting. Confirmation therefore has to be depth-based: record the receipt's blockNumber, compare it with eth_blockNumber, and act once the gap reaches the depth your strategy needs. Our cross-chain finality post shows how to pick that depth per action.
One more trap comes with the stack. On Robinhood Chain, block.number inside a contract returns an estimate of the Ethereum block number, not the L2 block number that eth_blockNumber and receipts report. A Base contract that compares a stored block.number with an off-chain block number works on Base and breaks on Robinhood Chain; use ArbSys(0x…64).arbBlockNumber() there.
Traces and conditional sends
Both chains serve debug_traceTransaction through Triport, with different terms. On Base, debug_traceTransaction and debug_traceBlockByNumber start at Pro and count against the heavy-read budget; the rest of Base's trace and proof surface is not part of the contract today. On Robinhood Chain, debug_traceTransaction and three sibling debug_* methods are available on every plan but are best-effort with no availability SLA, so a post-trade analytics job should retry and tolerate gaps rather than block the trading loop.
For sends that should land only if state still matches, Robinhood Chain has eth_sendRawTransactionConditional: five accepted options, -32602 for an invalid option, and a condition that no longer holds simply means no inclusion. That method is not part of Triport's Base contract today, so on Base the equivalent guard stays inside the contract you call (a deadline or a state check that reverts).
Rate budgets on one key
One Triport key serves both networks, and each network has its own budget per category. Values are sustained requests per second, with a 2× burst buffer on top, from the enforced tier matrix (Base limits, Robinhood Chain limits):
| Category | Free (7-day trial) | Basic | Pro | Business |
|---|---|---|---|---|
| Base reads | 10 | 20 | 100 | 250 |
| Base sends | 3 | 5 | 30 | 80 |
| Base heavy reads (incl. traces) | — | — | 2 | 5 |
| Robinhood Chain reads | 15 | 20 | 100 | 250 |
| Robinhood Chain heavy reads (logs, receipts, proofs, traces) | 15 | 20 | 100 | 250 |
| Robinhood Chain sends | 3 | 5 | 30 | 80 |
| Base Flashblocks feed streams | — | — | 1 | 2 |
| Robinhood Chain sequencer feed streams | — | — | 2 | 4 |
Two consequences for a bot. First, the budgets do not pool: a burst of Base reads does not eat into Robinhood Chain reads. Second, eth_getLogs is an ordinary read on Base and a heavy read on Robinhood Chain, so a log-polling loop moved over unchanged lands in a different bucket. On Robinhood Chain the WebSocket logs subscription is the alternative to polling when you follow a contract.
The change list
In the order we would do it:
- Network config: chain ID 4663, the keyed URL
https://triport.io/r/<YOUR_KEY>/robinhood, and a startupeth_chainIdcheck that refuses to run on the wrong chain. - Fees: drop tip bidding and replacement-by-fee on Robinhood Chain; keep estimation.
- Confirmation: replace
safe/finalizedreads with depth checks on the Robinhood Chain path. - Early data: a second feed adapter keyed by
sequenceNumber, withfrom_sequenceresume and an RPC backfill for gaps. - Contracts: audit every
block.number. - Sends that depend on state: on Robinhood Chain, consider the conditional method; on Base, keep the guard in the contract.
- Budgets: re-check which category each hot call falls into on each chain.
Start from the Base RPC endpoint and the Robinhood Chain RPC endpoint pages for URLs and plan details.
When this is the wrong approach
- Your bot only reads. A dashboard or an indexer that never sends transactions needs the confirmation and
block.numbersections and can ignore ordering and conditional sends. - You need the same execution guarantees on both chains. The ordering models are different by design. If your strategy depends on outbidding, it has no equivalent on Robinhood Chain, and porting it is the wrong project.
- You want the earliest possible view of the Robinhood Chain sequencer. This post compares the streams Triport serves. The sequencer feed is also published by Robinhood itself; which source suits you is a separate measurement on your own infrastructure.
Sources
- Base, Transaction Ordering — https://docs.base.org/specifications/transactions/transaction-ordering, read 2026-10-13 (priority fee and arrival time, Flashblock gas schedule from one tenth to the full limit, 2-second blocks).
- Base, Transaction Finality — https://docs.base.org/specifications/transactions/transaction-finality, read 2026-10-13 (Flashblock, L2 block about 2 seconds, L1 batch about 2 minutes, L1 finality about 20 minutes; withdrawal window 5 days or 1 day with dual proofs).
- Base, Base Protocol overview — https://docs.base.org/specifications/base-protocol/overview, and documentation index https://docs.base.org/llms.txt, read 2026-10-13 (single active sequencer, Reth-based execution, Optimism Isthmus and Jovian upgrades listed).
- Robinhood Chain, Differences from Ethereum — https://docs.robinhood.com/chain/differences-from-ethereum/, read 2026-10-13 (Arbitrum Nitro L2, first-come, first-served ordering, no priority gas auctions,
block.numberas an L1 estimate, ArbSys). - Robinhood Chain, overview — https://docs.robinhood.com/chain/, and Transaction Finality — https://docs.robinhood.com/chain/transaction-finality/, read 2026-10-13 (Arbitrum Dedicated Blockchains; three finality stages; 7-day challenge period).
- Triport capability registry and tier matrix, 2026-10-13: Base Flashblocks feed,
newHeads,debug_traceTransactionanddebug_traceBlockByNumberavailable; Robinhood Chain reads, heavy reads, fourdebug_*methods (best-effort), sends including the conditional method,newHeads,logsand the sequencer feed available; rates as in the table above. Docs: Base Flashblocks feed, Robinhood Chain sequencer feed, Base limits, Robinhood Chain limits. - RPC responses captured through Triport on 2026-10-13 at 17:37 UTC. Base:
eth_chainId0x2105,eth_blockNumber0x32207be,safeblock0x322079f,finalizedblock0x32205ac,eth_maxPriorityFeePerGas0xf4240. Robinhood Chain:eth_chainId0x1237,eth_maxPriorityFeePerGas0x0.