@bananapus/router-terminal-v6
v0.0.64
Published
`@bananapus/router-terminal-v6` is a routing terminal for Juicebox V6. It accepts value in many input tokens, discovers what token the destination project actually accepts, and forwards the payment through the best route it can resolve from the configured
Downloads
20,839
Readme
Juicebox Router Terminal
@bananapus/router-terminal-v6 is a routing terminal for Juicebox V6. It accepts value in many input tokens, discovers what token the destination project actually accepts, and forwards the payment through the best route it can resolve from the configured candidates.
Documentation
- INVARIANTS.md — runtime invariants enforced by the router, registry, and pay-route resolver.
- ARCHITECTURE.md — system overview, modules, trust boundaries, and critical flows.
- ADMINISTRATION.md — registry-owner and project-owner control surfaces, locking, and recovery.
- RISKS.md — accepted security risks (oracle, slippage, registry forwarding, token compatibility).
- USER_JOURNEYS.md — primary actor flows: paying, previewing, locking, and migrating.
- AUDIT_INSTRUCTIONS.md — scope, attack surfaces, and verification steps for auditors.
- SKILLS.md — agent-oriented index pointing at the right file or contract for a given task.
- STYLE_GUIDE.md — Solidity and repo-layout conventions used across the V6 ecosystem.
- CHANGELOG.md — v5 → v6 migration notes and in-v6 behavior changes for integrators.
Overview
The router terminal is a convenience and integration surface, not the source of truth for project accounting. Its job is to get value into the correct downstream terminal.
It can route through:
- direct forwarding when the destination already accepts the input token
- wrapping or unwrapping native ETH and WETH
- Uniswap V3 or V4 swaps
- recursive Juicebox token cash outs when the input is itself a project token
Projects can use the registry to choose, and optionally lock, a project-specific router terminal or fall back to the registry's default. The first setDefaultTerminal serves every project that already existed when it was called — including the canonical fee project (ID 1) — so those pre-existing projects can route tokens through the default. After that, the default is cohort-pinned: when the registry owner calls setDefaultTerminal again, the new default applies only to projects created after that call; existing projects continue to resolve against the default that was current when their ID range was active (see defaultTerminalFor(projectId)).
Use this repo when UX requires "pay with many tokens, settle into the right one." Do not use it as a replacement for downstream terminal accounting or as an authoritative decimal source.
This repo is best understood as an execution router attached to Juicebox, not as a new accounting model.
Key contracts
| Contract | Role |
| --- | --- |
| JBRouterTerminal | Main routing terminal that accepts many token types and forwards value to the destination terminal. |
| JBRouterTerminalRegistry | Registry and proxy surface that lets a project choose and optionally lock its preferred router terminal. |
| JBPayRouteResolver | Helper that evaluates pay-route candidates and selects the strongest route preview the router can resolve. |
Mental model
There are three separate decisions on the payment path:
- what token the destination project actually wants
- whether the input token can become that token directly, through a swap, or through a Juicebox cash-out path first
- which downstream terminal should receive the final asset
The router answers those questions, then hands off to the canonical terminal. It should not be treated as the system of record after that handoff.
The shortest useful reading order is:
JBRouterTerminalJBRouterTerminalRegistry- the downstream terminal selected through
JBDirectory
Read these files first
src/JBRouterTerminal.solsrc/JBRouterTerminalRegistry.solsrc/libraries/JBSwapLib.sol- the downstream terminal implementation in
nana-core-v6
Integration traps
- projects that expose a router terminal still settle into ordinary Juicebox terminals underneath
- route discovery and route execution are related but not identical, especially when liquidity or caller-supplied quote data moves
- using JB project tokens as router input creates recursive path complexity that frontends and integrators should model explicitly
- the registry changes which router a project uses, but not what downstream terminal ultimately settles the payment
Where state lives
- route-selection logic:
JBRouterTerminal - per-project router choice and lock status:
JBRouterTerminalRegistry - accepted-token accounting and final balance changes: the downstream terminal, usually in
nana-core-v6
That separation is why a successful route can still end in downstream terminal behavior you did not expect.
High-signal tests
test/RouterTerminal.t.soltest/RouterTerminalPreviewFork.t.soltest/RouterTerminalCashOutFork.t.soltest/regression/PreviewPrimaryTerminalMismatch.t.soltest/regression/CashOutCircularPrimaryTerminal.t.sol
Install
npm install @bananapus/router-terminal-v6Development
npm install
forge build --deny notes
forge test --deny notesUseful scripts:
npm run deploy:mainnetsnpm run deploy:testnets
Deployment notes
This package depends on core, address-registry, and permission-ID packages plus Uniswap V3, V4, and Permit2 integrations. It is meant to sit in front of canonical Juicebox terminals, not replace them.
Repository layout
src/
JBRouterTerminal.sol
JBRouterTerminalRegistry.sol
interfaces/
libraries/
structs/
test/
unit, fork, registry, review, invariant, and regression coverage
script/
Deploy.s.sol
helpers/Risks and notes
- the router synthesizes accounting context for discovery and should not be treated as an accounting-truth surface
- swap previews are best-effort estimates and depend on current pool state plus caller-supplied quote data
- recursive cash-out routing increases complexity when the input token is itself a Juicebox project token
- slippage and sandwich resistance depend on the quality of the chosen quote path
addToBalanceOfrejects lossy terminal pulls;paycannot reliably detect final-hop fee-on-transfer loss because pay hooks can consume tokens during settlement
The most common reader mistake here is to stop at the router and forget to inspect the terminal that actually receives the value.
For AI agents
- Do not claim the router is the accounting source of truth after forwarding.
- Read the preview, recursive cash-out, and registry tests before summarizing path selection behavior.
- If the route ends in surprising accounting, move to the downstream terminal in
nana-core-v6.
