Skip to content

Menu

Documentation

How Zusa Finance works

Zusa Finance compares the swap routes available on Robinhood Chain for one exact amount, shows what each route is expected to return and to cost, and lets you execute the one you choose from your own wallet. This page sets out what is compared, how routes are ranked, what is checked before your wallet is asked to sign, which contracts can be called — and what is not available yet.

This build
Robinhood Chain
chain 4663
Swaps
Available
through the verified venues below
Application fee
0 %
gas and venue fees still apply
Network facts verified
2026-10-05
against their published sources

01Overview

What Zusa Finance does

A non-custodial interface for swapping on Robinhood Chain. It does four things, and only these.

  1. I

    Compare available swap routes

    Every verified venue on the active network is asked for an exact-input quote on the same pair and amount: Uniswap V2, V3 and V4, read from their own contracts, and the KyberSwap aggregator, whose routes can split one order across several pools inside a single transaction. A venue that does not answer is listed with the reason.

  2. II

    Understand estimated costs and output

    Each route states its expected output, the minimum you will accept, the fees already inside its price, its gas estimate and — when it can be derived — its price impact. A figure that cannot be derived is shown as unavailable, never as zero.

  3. III

    Preview the execution path

    Before anything is signed you see the provider, every pool and hop, the contract the transaction is sent to, the approval it needs and the network it runs on.

  4. IV

    Swap through your own wallet

    Your wallet signs and broadcasts. Zusa Finance holds no funds, has no contract of its own and never asks for a private key or a seed phrase.

Networks and environments

A deployment serves exactly one network, chosen at build time with NEXT_PUBLIC_NETWORK. Activity, imported tokens and settings are stored separately for each network, so records from different environments never mix.

  • Mainnet

    this build

    Robinhood Chain

    chain 4663

    An Arbitrum Orbit L2 that uses ETH for gas. Quotes and swaps go through the verified venues listed under Contracts. No banner is shown.

  • Testnet

    Robinhood Chain Testnet

    chain 46630

    Uniswap publishes no deployment for chain 46630, KyberSwap’s aggregator does not list it and Chainlink publishes no feed directory for it. With no verified venue there are no quotes and no swaps — and no real liquidity or monetary value.

  • Development

    Local fork

    chain 4663 at 127.0.0.1:9341

    An Anvil fork of mainnet started with pnpm chain:fork: real contracts at the forked block, local state, no real funds, no explorer. Quotes and price feeds are read through the relay at 127.0.0.1:9342 — mainnet state at the live head — while balances, allowances, simulation and execution use the fork.

Testnet and local-fork deployments put a banner above the header of every application and documentation page — on the testnet it says there is no verified execution venue, no price feed and no real liquidity or monetary value; on a fork it says Development environment and that nothing there proves production behaviour — and label the network in the site footer. Mainnet shows neither. The network badge in the application header always names the active network and its chain id.

What this build can do

  • Chain reads available

    JSON-RPC reads on Robinhood Chain (chain 4663), relayed read-only to the browser through /api/rpc.

  • Uniswap V2 · V3 · V4 available

    Uniswap V2 Router02, V3 SwapRouter02 and the Universal Router (V4 pools, via Permit2), addresses from the official Uniswap deployment registry.

  • KyberSwap Aggregator available

    KyberSwap Aggregator API (chain slug "robinhood") with settlement through the Sourcify-verified MetaAggregationRouterV2.

  • Chainlink price feeds available

    Chainlink ETH/USD, USDG/USD and per-asset Stock Token feeds, read on-chain via AggregatorV3.

  • Stock Token registry available

    Official Robinhood Stock Token registry (api.robinhood.com/rhj) identifies tokenized equities by contract address.

  • Source verification available

    Source verification is looked up on Sourcify for chain 4663.

  • Block explorer available

    Blockscout at https://robinhoodchain.blockscout.com (links; its JSON API is read from your browser only).

02How it works

How it works

Four stages. Nothing reaches your wallet before the last one.

  1. 01

    Choose assets

    Pick what you pay and what you receive. The list holds the documented base assets and the Stock Tokens in the issuer’s registry; any other contract can be added by address and is labelled unverified. Decimals are read from the contract before an amount is converted, and choosing 100 % of an ETH balance keeps back the cost of 1,200,000 gas at the current gas price (5 % of the balance when no gas price can be read).

  2. 02

    Compare available quotes

    One request asks every verified venue for an exact-input quote on the same amount, each within its own 14-second limit so that a slow venue cannot hold the others. Every answer comes back — quotes, “no route”, “not configured” and errors — each with its reason.

  3. 03

    Review execution

    The review lists what your wallet will be asked to sign: the amount you pay, the expected and minimum output, provider and hops, recipient, transaction target, required approval, fees, estimated gas and the seconds left on the quote.

  4. 04

    Confirm in wallet

    Signing starts the sequence described under Review and execution — refresh, checks, an approval only if needed, simulation — and ends with your wallet’s own confirmation. The result is shown only after the receipt.

What a quote contains

Chain id
The network the quote was made for. A quote for another chain is never compared and never signed.
Provider and venue
Who quoted it — Uniswap V2, V3 or V4, or KyberSwap — and the pools behind the number.
Token addresses
The assets you pay and receive, by contract address; native ETH is written as “native”.
Input
The exact amount you pay, in the token’s base units. Amounts never travel as floating-point numbers.
Expected output
What the route is expected to return, before gas. Fees charged inside the venue’s pricing are already reflected in it.
Minimum output
The expected output less your slippage tolerance. The router reverts the swap rather than return less.
Route and pool details
Every hop with its venue, its pool (a pool id and hook for Uniswap V4), its fee tier and, for split routes, the share of the order each path takes.
Fee breakdown
Pool, protocol, hook, aggregator and application lines, each marked as inside the expected output or charged on top. The Zusa Finance line is 0 %: no application fee is configured.
Gas estimate
Gas units with their source — the quoter’s own meter, the provider’s estimate, or a labelled typical figure — and a USD value when ETH can be priced.
Timestamp and expiry
When the quote was produced. It is valid for 30 seconds; after that it must be refreshed before anything is signed.
Allowance target
The contract that needs your ERC-20 allowance: the router itself, or Permit2 for Uniswap V4. Native ETH needs none.
Execution target, value and calldata
Present once a wallet is connected: the contract the transaction goes to, the ETH attached and the exact data your wallet will be asked to sign.
Price impact
Against the pools’ mid price with the LP fee stripped (Uniswap), or KyberSwap’s own USD valuation of input and output. Shown as unavailable when it cannot be derived.
Warnings
Facts you must see before signing: an order split across several paths, a pool that runs hook code, a test sell-back the pool refused.

Venues compared on Robinhood Chain

  • Uniswap V3quotesexecutes

    QuoterV2 eth_call quotes across the direct pair on every fee tier and two-hop paths through WETH / USDG; executed through SwapRouter02 (exactInputSingle / exactInput, unwrapWETH9 for ETH output).

  • Uniswap V2quotesexecutes

    Constant-product quotes read on-chain from Router02.getAmountsOut across the direct pair and two-hop paths; executed through Router02 with the wallet as recipient.

  • Uniswap V4quotesexecutes

    Pools discovered from PoolManager Initialize logs, quoted one eth_call each by V4Quoter (hook fees included, slot0 read at the same block); executed through the Universal Router in one of three whitelisted shapes, ERC-20 input via Permit2.

  • KyberSwapquotesexecutesatomic splits

    Off-chain route search over the DEX pools Kyber indexes on this chain; atomic execution (including splits) through the Sourcify-verified MetaAggregationRouterV2, which enforces the minimum return itself.

  • 0x Swap APIawaiting configuration

    RFQ + on-chain aggregation through 0x. Needs an API key and verified settlement contracts for this chain before it can quote or execute here.

Requests, cancellation and stale responses

  • Each quote request is keyed on everything that changes its economics: your wallet’s network, your account, both tokens, the amount and the slippage tolerance.
  • Typing waits 350 ms before a request is sent, and changing any input cancels the request in flight.
  • A response is shown only while it answers the latest request and its inputs still match the screen. A late answer for an older input can never replace the quote for a newer one, whatever order the network delivers them in.
  • An expired quote on screen is refreshed automatically — up to six times in a row, only while the tab is visible, never while the review is open or a transaction is pending.
  • The review is bound to the account, network, tokens, amount, slippage tolerance and expiry it was opened with. When any of them changes the review no longer applies: a fresh quote must be read and reviewed before anything can be signed.

How routes are ranked

“Highest estimated net output among available quotes”

When
Two or more valid quotes, an output token with a USD price from a pinned Chainlink feed, and a USD gas estimate on every quote.
Ordering
Each route’s expected output is valued in USD, its gas cost in USD is subtracted, and the highest result ranks first.

“Highest expected output among available quotes — ranking excludes gas”

When
Two or more valid quotes, but the output token has no verified USD price or a provider reported no USD gas estimate. The reason is printed with the ranking.
Ordering
Routes are ordered by the amount of the output token alone. Gas is still shown for every route, so you can weigh it yourself.

One valid quote

When
Only one venue returned a valid quote for this request.
Ordering
It is presented as the only available route. Nothing is claimed about a comparison that did not take place.
  • Only comparable quotes are ranked: same chain, same asset in, same asset out, same input amount. Expired quotes, quotes without an output and quotes for another request or chain are excluded, and the reason is listed beside the comparison.
  • Nothing is subtracted twice. Pool, hook and aggregator fees charged inside a venue’s pricing are already inside its expected output and are not deducted again.
  • Native gas units are never subtracted from output-token units. Gas is paid in ETH. It enters the ranking only after both the output and the gas have been converted to USD, and stays out of it when either conversion is unavailable.
  • The output token’s USD price comes only from pinned Chainlink feeds — ETH/USD for ETH and WETH, USDG/USD for USDG, and the per-asset feed of a Stock Token resolved through the issuer’s registry — never from a symbol someone typed. Stock Token feeds run 24/5, so a weekend reading is used and labelled stale. Gas is valued with Chainlink ETH/USD or, when that feed is stale or cannot be read, with the Uniswap V3 WETH/USDG 0.01 % pool; the source is named next to the figure.
  • With two or more routes the comparison also says why the first ranks first: its extra output, or its net USD advantage, over the runner-up, with both gas figures.

03Execution

Review and execution

Pressing Sign sends nothing by itself. It starts a fixed sequence enforced by an explicit state machine: every step must pass before the next one runs, a failure stops the run with its reason, and a second run cannot start while one is in progress.

  1. Validate wallet, network and freshness

    A wallet must be connected, and the quote you reviewed is checked again against the browser’s own registry of verified contracts. An expired quote may continue, because the next step replaces it.

  2. Refresh the quote

    The provider you selected — only that one — is asked again for the same amount and slippage tolerance, with your address as the recipient.

  3. Present changed terms for a new review

    If the refreshed quote no longer matches what you reviewed, the run stops before any approval or signature and the review lists what changed: a different provider, network, token pair or amount; no executable route; an expected output or a minimum received more than 0.5 % lower; a different transaction target, approval spender, attached ETH or route. A better output never requires a new review.

  4. Check the transaction, the network and your balances

    The refreshed transaction must pass the signing guard described under Contracts. Your wallet is switched to Robinhood Chain if it is on another network, and your token balance and the ETH needed for gas are read.

  5. Approve only if needed

    If your allowance for the quote’s spender is below the amount, your wallet is asked to approve exactly that amount — unlimited only if you turned that on in the settings. Uniswap V4 sales go through Permit2: the token approves Permit2, then Permit2 allows the Universal Router to use exactly this amount for 30 minutes. Native ETH needs no approval.

  6. Wait for the approval receipt

    The approval must be mined with a successful receipt; a reverted, replaced or unconfirmed approval ends the run. Once it confirms, the run stops and a fresh quote is fetched — time spent approving can move the price — and you review and sign the swap from the first step.

  7. Simulate the actual transaction

    The exact transaction is executed with eth_call from your account against the current block, with the allowance already in place. Where the router returns its output — Uniswap V2, Uniswap V3, KyberSwap — the simulated amount must also reach the reviewed minimum.

  8. Wallet signature

    After a last expiry check your wallet is asked for exactly the reviewed transaction. Uniswap V4 swaps carry an explicit gas limit — the quoter’s figure plus 30 %, at least 350,000 — because hook code can make a wallet’s own estimate starve the swap; every other venue uses your wallet’s estimate.

  9. Track the submission and the receipt

    The hash is recorded as pending at once. The outcome comes only from the receipt — confirmed, reverted, replaced or unknown. After a confirmation your balances are read again and the activity record is updated.

What the panel shows

A swap with the allowance in place

  1. Re-checking…
  2. Refreshing quote…
  3. Checking balances…
  4. Simulating…
  5. Confirm in wallet…
  6. Pending…
  7. Confirmed

A run that needs an approval first (it stops for a fresh quote)

  1. Re-checking…
  2. Refreshing quote…
  3. Checking balances…
  4. Approve in wallet…
  5. Approval pending…
  6. Approval confirmed

Other ways a run ends

  1. Terms changed — review again
  2. Rejected in wallet
  3. Blocked
  4. Quote expired
  5. Reverted
  6. Replaced
  7. Status unknown

“Switching network…” appears between the quote refresh and the balance check when your wallet is on another network.

Slippage and deadline

The minimum received is the expected output less your slippage tolerance: expected × (10,000 − tolerance in basis points) ÷ 10,000. The tolerance defaults to 0.5 %, with presets of 0.1 %, 0.5 %, 1 % and 3 % and a ceiling of 50 %.

Both limits are enforced on-chain by the router, not by Zusa Finance. Router02 checks amountOutMin (Uniswap V2), SwapRouter02 and the Universal Router check amountOutMinimum (Uniswap V3 and V4), and MetaAggregationRouterV2 checks minReturnAmount for the whole order, split routes included (KyberSwap). Below the minimum the router reverts and the swap moves no funds.

Uniswap transactions carry a deadline 20 minutes after they were built — the V2 deadline argument, the SwapRouter02 multicall deadline, the Universal Router execute deadline — and the same 20 minutes is passed to KyberSwap’s build endpoint. A Uniswap transaction mined after its deadline reverts.

Simulation

Success

The transaction ran against the current block without reverting, from your account and with your allowance. Where the router reports its output, that amount also reached the reviewed minimum.

Failure

The call reverted, or the simulated output fell below the reviewed minimum. The run stops before your wallet is asked; nothing is sent.

Unavailable

The simulation could not run — typically the RPC did not answer. The run stops as well: Zusa Finance does not ask for a signature on a swap it could not simulate. Before a wallet is connected there is no transaction to simulate at all.

  • Insufficient allowance is handled before simulation. The approval step runs first, so a simulation never fails merely because the router cannot pull your tokens yet.
  • A gas estimate is not a security check. A transaction can estimate gas normally and still do something you did not intend; the protections are the decoded calldata, the verified target and the on-chain minimum.
  • A successful simulation does not guarantee later execution. Other transactions can move the price between the simulation and the block your swap lands in; the minimum received and the deadline are what protect you then.
  • The Universal Router returns no output value, so a Uniswap V4 simulation shows only that the swap does not revert; its minimum is still enforced on-chain.

When something goes wrong

Rejected signature
Shown as “Rejected in wallet”. Nothing was sent; you can start again from the review.
Reverted approval
The approval was mined but reverted. The swap is not attempted, and the activity record keeps the hash.
Reverted swap
Mined, but reverted: the gas was paid and the swap moved no funds. When the revert reason shows a price move beyond your slippage tolerance, it is named as such.
RPC failure
If a check cannot complete because the provider did not answer, the run stops and nothing is sent. A submitted transaction whose receipt cannot be read is never turned into a success or a failure: the panel says its status is unknown and that it may still confirm, the activity record stays pending, and it can be re-checked from Activity.
Expired quote
A quote older than 30 seconds is refused before signing; refresh it for a current price. A Uniswap transaction mined after its deadline is reverted by the router.
Insufficient gas
The balance check stops the run when your ETH cannot cover the amount sold plus gas or, for a token sale, the gas alone.
Replacement
Your wallet re-sent the same nonce, for example to speed it up. The original is marked replaced and the replacement’s hash is linked, with its own result.
Cancellation
Cancelling a pending transaction from your wallet is a replacement too, and is recorded as cancelled. Closing the review before signing sends nothing.
Unknown status
No receipt, the network no longer knows the hash, and its nonce was used by another transaction — dropped or replaced outside Zusa Finance. Check your wallet and the explorer.

A hash means submitted. Only a receipt means done.

“Confirmed” is shown only after a receipt with status success, together with the block number and a link to the transaction on Blockscout. A local fork has no explorer, so no link is shown there.

04Integrations

Integration inventory

Everything Zusa Finance relies on, the state it is in and where each fact comes from. The list is read live from /api/status, which adds probes of the providers that can be checked cheaply and caches them for 20 seconds. If that read fails, the static registry this build was configured with is shown instead — without probe results.

Running live probes…

Until /api/status answers, the registry is shown as this build was configured, without probe results.

As configured · probes running

13 verified2 awaiting configuration2 candidates

Verified and in use · 13

Checked against the source linked beside it, and used on this network.

  • Robinhood Chain JSON-RPC

    verifiedChain

    Public RPC (official host first, publicnode and dRPC as fallbacks) — chain 4663, relayed read-only to the browser through /api/rpc (method allow-list, no signing methods).

    docs.robinhood.com/chain/connecting
  • Blockscout explorer

    verifiedChain

    Blockscout at https://robinhoodchain.blockscout.com (links; its JSON API is read from your browser only).

    robinhoodchain.blockscout.com
  • Uniswap V3 QuoterV2

    verifiedQuotes

    Single-hop and two-hop exact-input quotes on the verified V3 factory pools (eth_call, no key).

    developers.uniswap.org/deployments.json
  • Uniswap V2 Router02.getAmountsOut

    verifiedQuotes

    Constant-product quotes on the verified V2 factory pairs.

    developers.uniswap.org/deployments.json
  • Uniswap V4 Quoter

    verifiedQuotes

    Pools discovered from PoolManager Initialize logs; V4Quoter simulates the real swap including hook fees.

    developers.uniswap.org/deployments.json
  • KyberSwap Aggregator API

    verifiedQuotes

    Key-free public API (x-client-id header), chain slug "robinhood"; route summaries with per-hop pools and split shares; calldata is decoded and checked against the request before it is offered to the wallet.

    docs.kyberswap.com/kyberswap-solutions/kyberswap-aggregator/agg…
  • Uniswap routers (V2 Router02 / V3 SwapRouter02 / Universal Router + Permit2)

    verifiedExecution

    Uniswap V2 Router02, V3 SwapRouter02 and the Universal Router (V4 pools, via Permit2), addresses from the official Uniswap deployment registry.

    developers.uniswap.org/deployments.json
  • KyberSwap MetaAggregationRouterV2

    verifiedExecution

    Sourcify exact match (creation + runtime). The router itself enforces the minimum return for the whole order, split routes included; Zusa Finance refuses payloads with fee lines, permits or payment-altering flags.

    sourcify.dev/server/v2/contract/4663/0x6131…37b5
  • Chainlink price feeds

    verifiedPrice feeds

    Chainlink ETH/USD, USDG/USD and per-asset Stock Token feeds, read on-chain via AggregatorV3.

    docs.robinhood.com/chain/oracles-and-price-feeds
  • Robinhood Stock Token registry

    verifiedToken data

    Official Robinhood Stock Token registry (api.robinhood.com/rhj) identifies tokenized equities by contract address.

    docs.robinhood.com/chain/stock-token-apis
  • Sourcify source verification

    verifiedVerification

    Source verification is looked up on Sourcify for chain 4663. "Not verified" is reported as such, never hidden, and is not a safety rating.

    sourcify.dev
  • Blockscout records (browser)

    verifiedVerification

    The explorer API challenges server-side callers, so wallet history is read from the visitor’s browser and labelled "read from your browser".

    robinhoodchain.blockscout.com
  • Injected wallets (EIP-6963 / EIP-1193)

    verifiedWallets

    Browser-extension and in-app wallets. Transactions are signed and broadcast by the wallet; Zusa Finance never handles keys or seed phrases.

    eips.ethereum.org/EIPS/eip-6963

Awaiting configuration · 2

Implemented, but not offered until the configuration it needs exists.

  • 0x Swap API

    awaiting configurationQuotes

    Needs ZEROX_API_KEY (server-side; the API refuses key-less requests) and verified settlement contracts for chain 4663. The typed adapter is in place; until then it reports "not configured".

    0x.org/docs
  • WalletConnect

    awaiting configurationWallets

    Needs NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID and a connector build that excludes the Coinbase SDK. Not offered until then.

    docs.reown.com

Probed but not integrated · 2

Answers for this chain, but its settlement contract and calldata are not verified here, so it could not pass the signing guard.

  • LI.FI (candidate)

    candidateQuotes

    Lists Robinhood Chain (4663) and answers same-chain quotes. Not integrated: its settlement contract on this chain and calldata shape have not been verified or decoded here, so it cannot pass the signing guard.

    li.quest/v1/chains
  • Relay (candidate)

    candidateQuotes

    Lists Robinhood Chain (4663, token support "All") and answers same-chain quotes. Not integrated for the same reason: unverified settlement contract and undecoded calldata.

    api.relay.link/chains

On Robinhood Chain the live probes are the JSON-RPC endpoint (latest block), the Stock Token registry (tokens listed for this chain), the Chainlink ETH/USD feed (price and age) and the KyberSwap API (a 0.001 WETH → USDG route, and whether the router it names matches the pinned one). A verified entry whose probe fails is shown as degraded until a later probe succeeds.

Probed but not integrated. LI.FI and Relay list Robinhood Chain and answer same-chain quotes, but their settlement contracts and calldata have not been verified and decoded here, so they could not pass the signing guard and are not offered. Awaiting configuration. 0x needs a server-side API key and verified settlement contracts for chain 4663; WalletConnect needs a project id and a connector build that leaves out the Coinbase SDK. Until then both are listed as they are.

What the states mean

verified
Checked against the source linked beside it, and used on this network.
development
Local fork only: the real contracts at the forked block, local state, no real funds.
degraded
Configured, but its live probe failed just now — or a key is set while a fact it depends on is still unverified.
awaiting configuration
Implemented, but not offered until the configuration it needs exists.
candidate
Answers for this chain, but its settlement contract and calldata are not verified here, so it could not pass the signing guard.
unsupported
No verified deployment or coverage exists for the active network.

05Contracts

Contracts the app may call

Zusa Finance can ask your wallet to send a swap to, or grant an allowance to, only the contracts below. Each provider has exactly one swap target and one approval spender; an approval itself is a call to the token you sell, naming that spender.

Signing guard

Before every signature the browser re-checks the transaction target and the approval spender against this registry — its own copy, not the server’s answer — and refuses anything else. A Uniswap V3 quote cannot be sent to the V2 router, a KyberSwap quote cannot be sent to the Universal Router, and no swap can be sent to, and no allowance granted to, an address that is not listed here.

Signing targets and approval spenders

What is checked in the calldata

  • The quote is for the active network and has not expired.
  • The target is the single verified contract for the quote’s provider, and the spender its single verified spender. Permit2 is accepted only for Uniswap V4 quotes.
  • The calldata is decoded with the decoder of the target contract itself and must show: the output going to your connected wallet; a route that starts and ends at the tokens you reviewed; the amount you entered as the amount spent; the reviewed minimum as the minimum output; and exactly the ETH the payload spends as the value attached — zero for a token sale.
  • A Universal Router payload must take one of exactly three shapes — swap; wrap ETH, then swap; swap, then unwrap to ETH — and re-encode to the very same bytes.
  • A KyberSwap payload must call swap with no fee lines, no permit and none of the flags that change what the wallet pays, and the router address in KyberSwap’s answer must equal the pinned one. The server applies these checks before the quote reaches your browser, and the browser applies them again.

Uniswap V4 and Permit2

Uniswap V4 quotes use the Universal Router as their target and Permit2 as their only ERC-20 spender. Selling a token therefore takes two approvals: the token approves Permit2, then Permit2 allows the Universal Router to use exactly the sale amount for 30 minutes. An existing Permit2 grant with less than 5 minutes left is renewed, so it cannot lapse between the check and the swap. Both addresses are compared with the registry above before anything is signed.

Read-only contracts

Read by the server for quotes, pool discovery and prices. None of them is ever a swap target or an approval spender.

06Tokens

Token identity

A token is identified by its contract address on the active network — never by its name, its ticker or its logo.

documented

Documented base assets

Native ETH and the canonical tokens published on Robinhood Chain’s contracts page — WETH and USDG on mainnet.

issuer registry

Robinhood Stock Tokens

Tokenized equities whose contract address is listed in the issuer’s registry.

unverified

Imported tokens

Any other contract, added by its address and labelled unverified wherever it appears.

Documented base assets on Robinhood Chain

Robinhood Stock Tokens

A Stock Token is recognised only by its contract address, through the official registry at api.robinhood.com/rhj/assets (issuer: Robinhood Assets (Jersey) Limited). A token that copies a ticker or a name is not a Stock Token here. The registry lists mainnet deployments only; it is refreshed every 10 minutes and served from cache for up to an hour if it cannot be reached.

Looking a Stock Token up also reads its ERC-1967 beacon slot. Every official Stock Token is a beacon proxy whose beacon is the issuer’s AccessControlsRegistry (0xe10b6f6B275de231345c20D14Ab812db62151b00); a listed token whose slot points elsewhere is flagged to be treated with suspicion.

Stock Tokens do not rebase on-chain: balances are raw units and the corporate-action multiplier is for display only, so they route like any ERC-20. The issuer can pause transfers. See the issuer’s Stock Token documentation.

Imported tokens, and what is never assumed

  • Any contract can be added by its address. Symbol, name and decimals are read from the contract itself; the token is labelled unverified wherever it appears and is kept in this browser, for this network only.
  • A matching name or symbol proves nothing. Verify the address yourself.
  • Source verification is looked up on Sourcify and shown as found. “Not verified” is reported as such — it is not evidence of anything by itself, and it is not a safety rating.
  • A contract that reports no ERC-20 decimals cannot be traded, because amounts could not be converted safely.
  • Fee-on-transfer and rebasing tokens are not supported. A transfer tax makes the amount received smaller than the router’s minimum check expects, and a rebasing balance breaks exact approvals.
  • No token is trusted merely because it can be imported.

07Activity

Activity and data integrity

The Activity page lists the approvals and swaps submitted through Zusa Finance from this browser. It is not a complete wallet history.

Where records live

  • Records are kept in this browser’s local storage, in a separate store for each network (zusafinance:mainnet:activity for this build), so mainnet, testnet and a local fork never mix. Each record carries the submitting account and the chain id, and the page shows only the connected account on the active network. Up to 300 recent records are kept.
  • There is no account system, no server copy and no sync. Another browser or device shows nothing, and clearing this site’s data removes the list.
  • “Clear settled” removes the connected account’s settled records; pending ones stay.

Statuses

  • pendingSubmitted; no receipt yet.
  • confirmedMined with a successful receipt.
  • revertedMined, but the transaction reverted — gas was paid, the swap moved no funds.
  • replacedThe wallet re-sent the same nonce (sped up or cancelled); the replacement is linked.
  • unknownThe network no longer knows the hash and its nonce was used by another transaction, or the RPC did not answer.

Statuses come from receipts. Every record still pending or unknown is followed again when the app loads, and on demand with Re-check; each attempt waits up to three minutes for a receipt. A transaction is never moved from pending to a success or a failure without one. The gas paid is gasUsed × effectiveGasPrice from the receipt, never an estimate.

Explorer history, read from your browser

On Robinhood Chain a second section lists the transactions the wallet sent, as indexed by Blockscout — the newest 25 — fetched directly by your browser, because the explorer’s API challenges server-side readers. It is labelled as read from your browser, its coverage is the explorer’s rather than Zusa Finance’s, and when the explorer does not answer the section says so. The testnet and a local fork have no explorer API here, so the section is absent there.

08Environment

Environment setup

A Next.js application that needs no secret to run against mainnet. Requirements: Node 20 or later and pnpm 9; Foundry’s anvil only for the local fork.

Quick start
pnpm install
cp .env.example .env.local     # nothing secret is required
pnpm dev                       # http://localhost:22900

Environment variables

NEXT_PUBLIC_NETWORKpublic
Active network: mainnet (Robinhood Chain, 4663, the default), testnet (46630) or local (the Anvil fork on 127.0.0.1:9341). Read at build time; one deployment serves one network. On the testnet quotes and swaps are disabled with the reason shown; local is labelled as a development environment.
NEXT_PUBLIC_SITE_URLpublic
Canonical URL for metadata and Open Graph tags. On Vercel it falls back to the project’s production URL; set it explicitly once a custom domain is attached. Local default http://localhost:22900.
NEXT_PUBLIC_X_URL · NEXT_PUBLIC_X_HANDLEpublic
Optional official X account: the full URL and the handle. Nothing is rendered while they are empty.
ROBINHOOD_RPC_URLserver only
Optional private mainnet RPC endpoint — Robinhood’s documentation recommends a provider for production, as the public RPC is rate limited under load. Tried before the public endpoints, read only by server routes and the read-only relay, never shipped to the browser. Ignored by the local fork.
ROBINHOOD_TESTNET_RPC_URLserver only
The same, for a testnet build.
RESOLVE_OVERRIDEserver only
Local development only: DNS pins written as host=ip,host=ip, for networks whose resolver hijacks robinhood.com. TLS still validates the real certificate. Leave it empty in production.
KYBER_CLIENT_IDserver only
Sent as the x-client-id header to KyberSwap’s key-free aggregator API, whose documentation asks integrators to identify themselves. Default ZusaFinance.
ZEROX_API_KEYserver only
Optional. Without it the 0x adapter reports “awaiting configuration” and is skipped; with it the adapter stays inert until 0x settlement contracts for this chain are verified and pinned.
NEXT_PUBLIC_WALLETCONNECT_PROJECT_IDpublic
Optional WalletConnect project id. Unset, only injected wallets are offered. Set, WalletConnect is still not offered by this build — its connector is not bundled — and the inventory reports it as degraded.

Variables with the NEXT_PUBLIC_ prefix are public by design: Next.js can inline them into the browser bundle at build time, so they never hold a secret and changing one needs a rebuild. Everything else is read only by server code. The full annotated list is in .env.example.

Commands

pnpm dev
Development server on http://localhost:22900.
pnpm build
Production build (next build).
pnpm typecheck
TypeScript, without emitting files.
pnpm lint
ESLint with the Next.js rules.
pnpm test
Unit tests (vitest): comparison and ranking rules, signing guards, KyberSwap and Uniswap V4 calldata, the trade state machine, receipt classification, RPC fallback, sanitisation, stores and amount conversion.
pnpm verify:config
Re-checks every pinned network fact against its live source — chain ids, Uniswap’s registry, bytecode at every pinned address, router wiring, the KyberSwap router and API, the Chainlink feeds, the Stock Token registry, the fallback RPCs, Sourcify. Read-only; run it before every deploy.
pnpm smoke [url]
Calls every page and API route of a running server (default http://localhost:22900) and checks each status code.
pnpm chain:fork
Starts the relay on 127.0.0.1:9342 and an Anvil fork on 127.0.0.1:9341, funds one of Anvil’s published test accounts and writes .env.fork. Needs Foundry’s anvil.
pnpm dev:fork
The app against the fork on http://localhost:22910 (NEXT_PUBLIC_NETWORK=local, separate build directory .next-fork).
pnpm e2e:fork
Sends the exact calldata /api/quote returns to a fresh fork — ETH → USDG through every venue, then USDG → ETH with an exact approval through KyberSwap and Uniswap V3 — and checks the minimum was received. Needs pnpm dev on 22900; starts its own fork, so stop chain:fork first.
pnpm flow:fork
Headless Chrome flow with a stub wallet against pnpm dev:fork: wrong-network switch, quotes, review, exact approval, simulation, signature, receipt, a rejected signature, an expired quote, activity after a reload.

Local fork rehearsal

The execution path can be rehearsed end to end on an Anvil fork of mainnet: the real deployed contracts, local state, Anvil’s published test accounts, no real funds and no real key. Every application page says Development environment, and a rehearsal proves the calldata and the flow — not production behaviour.

Three terminals
pnpm chain:fork      # relay 127.0.0.1:9342 → public RPC, Anvil fork on 127.0.0.1:9341, writes .env.fork
pnpm dev:fork        # http://localhost:22910 with NEXT_PUBLIC_NETWORK=local
pnpm flow:fork       # headless browser flow with a stub wallet

# Separately, with `pnpm dev` (mainnet) running on 22900 and chain:fork stopped:
pnpm e2e:fork        # the app's own calldata, executed on a fresh fork

Deploying on Vercel

  • pnpm ship runs vercel --prod --yes for the team configured in package.json and uploads the project folder; no git remote is needed. vercel.json pins the Next.js framework preset.
  • Set variables in the Vercel project settings. Credentials — ROBINHOOD_RPC_URL, ZEROX_API_KEY — go without the NEXT_PUBLIC_ prefix, so only server code reads them: the browser reaches the chain through /api/rpc and the providers through the application’s own API routes.
  • Production builds keep NEXT_PUBLIC_NETWORK=mainnet (the default) and an empty RESOLVE_OVERRIDE. Set NEXT_PUBLIC_SITE_URL once a custom domain is attached.
  • Before a deploy run pnpm verify:config, the type check, lint, tests and a build; after it, run pnpm smoke <production URL> and open this page’s integration inventory to see the live probes.

09Security

Security

What the server will and will not do on your behalf, what the browser checks for itself, and what does not exist at all.

The quote proxy

  • Input is validated before anything is fetched: each asset is “native” or a 20-byte hex address, the amount a positive integer in base units (never a float), the slippage tolerance 1–5,000 basis points, the provider filter a value from a fixed list. Bodies over 64 KB are refused.
  • Upstreams are fixed by server configuration — the configured RPC endpoints, KyberSwap’s aggregator API for this network’s chain slug, the Chainlink feed directory and the Stock Token registry — and the chain is fixed by the build. Nothing in a request can choose a host, and no route forwards to a URL supplied by the caller.
  • Every venue has its own time limit — 14 seconds, with 9 seconds each for KyberSwap’s route search and build — so a slow provider fails alone.
  • Requests are rate limited per client IP: quotes 60 a minute, the RPC relay 300, status 60, the token list 60, token look-ups 120.
  • Credentials are read in one server-only module and never returned in a response. The application code writes no logs of requests or credentials.

The RPC relay

/api/rpc forwards JSON-RPC to the configured upstream only, and only these read methods:

eth_chainIdeth_blockNumbereth_calleth_estimateGaseth_gasPriceeth_maxPriorityFeePerGaseth_feeHistoryeth_getBalanceeth_getCodeeth_getStorageAteth_getTransactionCounteth_getBlockByNumbereth_getBlockByHasheth_getTransactionByHasheth_getTransactionReceipteth_getLogsnet_version

Nothing that signs or broadcasts passes — eth_sendRawTransaction is refused — because your wallet broadcasts its own transactions. A batch holds 1 to 100 calls and at most 200 KB, and an upstream that refuses a query for a provider limit is skipped for the next configured one.

What the browser shows and loads

  • Token names and symbols come from contracts and registries and are treated as hostile input: control and bidirectional-override characters are stripped and lengths capped before display, and React escapes the rest.
  • No remote token images. Tokens are drawn as a glyph made from their symbol; no image is fetched from a token list, a contract or a third-party host.
  • Every response carries X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin and a Permissions-Policy that turns off camera, microphone and geolocation.

What does not exist

  • No custody contract

    Zusa Finance deploys no contract and holds no funds. A swap goes from your wallet straight to the verified router, and the calldata check ensures the router pays your wallet.

  • No staking or yield

    Zusa Finance has no staking and no yield product, and charges no application fee: the fee line in every quote is 0 %. The project token $ZUSAFI is announced on the home page — “CA: Soon” until its contract address is published — with no claimed utility, yield or staking.

  • No key handling

    Transactions are signed and broadcast by your wallet. Zusa Finance never asks for a private key or a seed phrase.

10Limitations

Limitations and blocked dependencies

What Zusa Finance cannot do today, and why. Each item is a fact about a dependency or a deliberate scope, stated as it is.

  • Testnet execution

    unsupported by fact

    No Uniswap deployment for chain 46630, no KyberSwap coverage and no Chainlink feeds. The testnet has no quotes and no swaps by fact, not by choice.

  • WalletConnect

    awaiting configuration

    Needs NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID and a connector build that leaves out the Coinbase SDK, whose dependency tree breaks production builds. Until then only injected wallets — browser extensions and in-app browsers — are offered.

  • 0x Swap API

    awaiting configuration

    Needs ZEROX_API_KEY on the server — the API refuses requests without a key — and 0x settlement contracts for chain 4663 verified and pinned here. The adapter reports “not configured” until both exist.

  • Private RPC

    optional

    The public RPC is rate limited under load. ROBINHOOD_RPC_URL adds a private endpoint, tried before the public ones, for production volume.

  • Public RPC batch and log limits

    provider limit

    The public Robinhood RPC drops answers from large concurrent JSON-RPC batches, so batches stay small — 16 calls on the server, 20 from the browser — and a failed read is retried once. It also caps eth_getLogs ranges, so Uniswap V4 pool discovery scans the PoolManager’s logs newest-first in bounded windows (at most 24 queries per pair) and treats a capped scan as incomplete rather than as “no pools”.

  • Explorer API

    browser only

    Blockscout challenges server-side callers, so wallet history is read from your browser and labelled as such. There is no server-side history.

  • Activity

    browser only

    Activity is stored in this browser only, and no indexer of complete wallet history stands behind it.

  • Price impact

    shown as unavailable

    When no mid price can be read for a route — or KyberSwap reports no USD valuation — price impact is shown as “Unavailable”. The minimum received still protects the swap.

  • Route shapes

    scope

    Exact-input swaps only. Uniswap V4 routes use a single pool; Uniswap V2 and V3 routes are direct or two-hop through WETH or USDG; KyberSwap routes may split. ETH ↔ WETH is a wrap, not a swap, and is not quoted.

  • Local fork

    development only

    Quotes and price feeds reflect mainnet at the live head while execution uses the fork’s state, and Uniswap V4 pools created on the fork itself are not discovered. A rehearsal proves the calldata, not production behaviour.

  • Rate limits

    per instance

    Request limits are kept in memory by each server instance: enough to blunt accidental loops, not a global quota.

Chain ids, contract addresses, sources and capability notes on this page are rendered from the same configuration the application runs on, and the integration inventory is read live. Network facts were last verified on 2026-10-05. Nothing here is investment advice.

Open the swapActivityBack to the top