Skip to content

Add Robinhood Chain support - #1087

Merged
j0ntz merged 4 commits into
masterfrom
jon/robinhood-chain
Aug 28, 2026
Merged

j0ntz merged 4 commits into
masterfrom
jon/robinhood-chain

Conversation

@j0ntz

@j0ntz j0ntz commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Technical Design Document

robinhood-chain.md

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Description

Adds Robinhood Chain (robinhood, EVM chain 4663) as a currency plugin. It is an Arbitrum Nitro L2 with ETH as its gas token, so the plugin is configuration only: arbitrumRollupParams selects the existing NodeInterface L1-component fee path, and no engine code changes.

Asana: https://app.asana.com/1/9976422036640/project/1213843652804305/task/1217382370104887

Three choices worth a reviewer's attention, all covered in the design doc:

History comes from Blockscout, not Etherscan. Etherscan V2 does not serve chain 4663 (Missing or unsupported chainid parameter; 4663 is absent from its /v2/chainlist). Routescan returns chain not supported, and HoodScan has no Etherscan-compatible API. Blockscout is the only source that answers, and it has no gastracker or proxy module, hence gastrackerSupport: false and the RPC adapter declared first so nonce and block-height lookups do not hit the missing proxy module.

Built-in token addresses come from the canonical bridge, not a token search. This chain's explorer lists imitations that outrank the real contracts by holder count, including a 30,726-holder "USDC" named Universal Stable Digital Coin. Each bridged address was derived by calling calculateL2TokenAddress(l1Token) on the L2 Gateway Router from Robinhood's published contract list. USDG, CASHCAT and PONS are issued natively rather than bridged. USDG was confirmed as a verified ERC-1967 proxy whose implementation is named USDG. CASHCAT (0x020bfC65…) and PONS (0x39dBED3a…) are each corroborated by more than one swap provider settling to that address, ChangeNow, Swapuz, LetsExchange and Rango for CASHCAT and Swapuz and Rango for PONS, and then confirmed against the contract itself: name() "Cash Cat" / "Pons", symbol() CASHCAT / PONS, decimals() 18 for both, with deployed bytecode present. A single provider catalogue is not sufficient on its own, since a provider can list a wrong address as easily as an explorer can.

addressQueryLookbackBlocks is 1250, not the 480 copied from Arbitrum. Blocks arrive about every 96ms here (measured: 626 blocks in 60.2s), so 480 blocks is a 46-second re-scan overlap rather than the ~2 minutes the constant means on other chains.

No ethBalCheckerContract: none of the five balance-checker addresses used across Edge's EVM plugins has code on this chain. Multicall3 is deployed at the canonical address but implements a different ABI, so it is not a substitute.

Testing. Full npm test and tsc pass; test/builtinTokens.test.ts covers all seven token IDs, deriving each from its entry and asserting the key matches. Both configured RPC servers agree on eth_chainId (0x1237), block height, balance and nonce, and the NodeInterface call at 0x…C8 returns a base fee, confirming the Arbitrum fee path applies. The second server started as rpc.arrowrpc.com; a pre-merge review found it dead (HTTP 530, Cloudflare error 1033) and it was replaced with robinhood-rpc.publicnode.com, re-verified through the plugin's own request shape and asRpcResultString cleaner on all four methods plus gasEstimateL1Component. Driven in-app on the iOS simulator with this branch linked in: the wallet creates, and importing a seed with real on-chain history renders 0.000000019866 ETH, matching eth_getBalance for that address.

Transaction history was verified under a forced response, since the live endpoint rate-limits this host. The public Blockscout /api returns HTTP 429 after a handful of requests from one egress address and recovers after about three minutes, and the simulator's own polling shares that budget. Its v2 API has a separate quota, which is where the address's two real rows came from. fetchGetEtherscan was then temporarily stubbed to return those rows, leaving the cleaner, processEvmScanTransaction and the list component untouched, and both rendered correctly: "Sent Ethereum -Ξ 0.011497, Jul 15 2026" and "Received Ethereum +Ξ 0, Aug 1 2026", matching the chain exactly (21000 gas at 56,326,000 wei on the outgoing transfer). The stub was reverted; screenshot attached below and marked as hack-forced.

HTTP 429 already raises RateLimitError and retries with exponential backoff, so no handling is missing here. A Blockscout API key would remove the ceiling with no code change, since EvmScanAdapter already appends &apikey=. No Edge-held provider key covers chain 4663: Etherscan V2 does not serve it, the dRPC key is deactivated account-wide, nowNodes and quiknode have no endpoint, and Alchemy supports the network but answers ROBINHOOD_MAINNET is not enabled for this app.

Follow-ups, none blocking this PR:

  • ROBINHOOD_INIT needs adding to the deployed env.json, or the plugin ships disabled.
  • Currency icons at content.edge.app/currencyIconsV3/robinhood/ (robinhood.png, chain_robinhood.png) do not exist yet, so wallets render a text placeholder.
  • Edge's rates server has no entry for robinhood, so ETH on the chain prices at $0 throughout the app.

Update: send is now verified. The claim that no swap provider quotes chain 4663 was wrong: it was inferred from the chain's absence in Edge's own provider maps rather than checked against a provider API. A sweep of the provider discovery endpoints found six advertising the chain; edge-exchange-plugins#483 maps four of them. With that branch served in, a swap from Sonic funded a Robinhood Chain wallet with 0.006248511112300593 ETH, and a 0.001 ETH send from it is transaction 0x70e4950b5991c9419eff70ea2478c7ae55c5c58adcc3da237d5889394f8fdf62, success in block 35308086. Send and fee estimation on this chain are exercised, not deferred. The design doc's phase history and retrospective are updated accordingly.


Note

Medium Risk
New user-facing chain and seven curated token contracts on an explorer full of impersonators; correctness depends on config and third-party RPC/Blockscout availability, though no shared engine logic changes.

Overview
Adds Robinhood Chain support as a new EVM currency plugin (pluginId robinhood, chain ID 4663, native ETH gas) by wiring existing EthereumEngine behavior through a new robinhoodInfo.ts and registering it in ethereumInfos.ts.

The network config targets this chain’s quirks: RPC first, then Blockscout for history (Etherscan V2 does not cover 4663), gastrackerSupport: false, arbitrumRollupParams for Nitro L1 fee estimation, a 1250-block history lookback (~2 minutes at ~96ms blocks), and a lowered 0.01 gwei minPriorityFee. Built-in tokens are USDC, USDT, USDG, WBTC, WETH, CASHCAT, and PONS, with bridged addresses from the gateway router and chain-native ones corroborated off-provider settlement addresses—not explorer search.

Also adds an Unreleased CHANGELOG entry and a long src/docs/robinhood-chain.md design note covering cross-repo GUI, swap, and rates follow-ups.

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

@j0ntz

j0ntz commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor Author

📸 Test evidence

live balance from chain

live balance from chain

robinhood in create wallet

robinhood in create wallet

Captured by the agent's in-app test run (build-and-test).

@j0ntz
j0ntz marked this pull request as ready for review August 13, 2026 00:01
@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch from 9bf076d to 698c5ca Compare August 13, 2026 00:01
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch from 698c5ca to ddb3379 Compare August 13, 2026 00:19
@j0ntz

j0ntz commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor Author

📸🪓 Transaction history (hack-forced)

🪓 Hack-forced evidence: EvmScanAdapter.fetchGetEtherscan temporarily stubbed to return two real txlist rows captured from this chain's Blockscout v2 API, because the free tier 429s this host; the cleaner, processEvmScanTransaction and the list component all ran unmodified. Stub reverted, git status clean. Temporary uncommitted edit, reverted before commit; the marked frames prove the rendering, not the trigger.

🪓 HACK-FORCED: tx list

🪓 HACK-FORCED: tx list

Captured by the agent's in-app test run (build-and-test).

@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch from ddb3379 to 5f04c09 Compare August 13, 2026 01:14

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5f04c09. Configure here.

Comment thread src/ethereum/info/robinhoodInfo.ts
@cursor

cursor Bot commented Aug 27, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@j0ntz j0ntz closed this Aug 27, 2026
@j0ntz j0ntz reopened this Aug 27, 2026
@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch 4 times, most recently from 09495bb to e01766a Compare August 28, 2026 22:38
Comment thread src/ethereum/info/robinhoodInfo.ts
@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch from e01766a to 57c02ba Compare August 28, 2026 22:50
j0ntz added 4 commits August 28, 2026 15:58
Robinhood Chain is an Arbitrum Nitro L2 (chain 4663) using ETH for gas.
Etherscan V2 does not cover this chain, so transaction history comes from
its Blockscout instance, which has no gastracker or proxy module; the RPC
adapter is listed first so nonce and block-height lookups go there.

The chain's explorer lists many same-symbol imposters, so no built-in
token address comes from a name lookup. The bridged four resolve through
the L2 gateway router. USDG, CASHCAT and PONS are issued on the chain
itself, so each is corroborated by more than one swap provider settling
to that address and then confirmed against the contract's own name,
symbol and decimals.
Documents the shipped plugin: why an Arbitrum rollup config rather than
an Optimism one, why Blockscout is the only usable history source, and
how the built-in token addresses were derived from the canonical bridge
rather than read off an explorer's token search.
Phase 1 recorded that no swap provider quotes chain 4663 and deferred a
funded send on that basis. A direct sweep of the provider APIs found six
advertising the chain, three of which fill orders into it, so the doc now
carries an edge-exchange-plugins section, the swap and send verification,
and a retrospective note that the non-goal was inferred from Edge's own
mapping files rather than checked against a provider.
Records the rates-server work as section 8 and phase 3: what the v3 API
keys on, which maps register the chain, and why only half of the change
reaches a running server on deploy.

Adds phase 4, the pre-merge review pass, and the RPC endpoint swap it
forced after the original fallback went dark.

Adds phase 5, the full provider audit, and rewrites section 7's provider
table from probing every provider rather than only the ones with
synchronizers.

Adds phase 6 and the chain-native token provenance, covering why the
exchange side needed no change to reach the new tokens.
@j0ntz
j0ntz force-pushed the jon/robinhood-chain branch from 57c02ba to ff6b61a Compare August 28, 2026 23:01
@j0ntz
j0ntz enabled auto-merge August 28, 2026 23:01
@j0ntz
j0ntz merged commit b3f7fb9 into master Aug 28, 2026
4 checks passed
@j0ntz
j0ntz deleted the jon/robinhood-chain branch August 28, 2026 23:10
@j0ntz
j0ntz restored the jon/robinhood-chain branch August 28, 2026 23:30
@j0ntz
j0ntz deleted the jon/robinhood-chain branch September 1, 2026 22:39
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