Router Architecture

The Fira Router uses a diamond-like proxy pattern where each function selector maps to a specialized action facet via delegatecall.

Overview

The FiraRouterV4 is the single entry point for all user-facing protocol operations. It extends OpenZeppelin's Proxy and uses a selector-to-facet mapping to delegate every call to the appropriate action contract.

circle-info

Since the proxy uses delegatecall, all facets share the same storage. RouterStorage uses ERC-7201 storage namespacing (a hashed storage slot) to avoid collisions with any facet's own storage layout.

How it works

Call routing

When a user calls any function on the router:

  1. The fallback() function reads msg.sig (the 4-byte function selector)

  2. Looks up the registered facet address in CoreStorage.selectorToFacet[msg.sig]

  3. If no facet is registered, reverts with INVALID_SELECTOR

  4. Otherwise, delegatecalls into the facet contract

Initialization

The constructor takes two arguments: the owner address and the ActionStorageV4 facet address. It hard-wires the setSelectorToFacets and selectorToFacet selectors to the storage facet so the owner can configure all other mappings post-deployment.

Upgrading

The owner can update selector-to-facet mappings at any time via ActionStorageV4.setSelectorToFacets. This allows:

  • Adding new features — Register new selectors pointing to new facet contracts

  • Fixing bugs — Point existing selectors to updated facet implementations

  • Removing features — Set a selector's facet to address(0) to disable it

No state migration is needed because all facets share the router's storage via delegatecall.

Facet contracts

Facet
Responsibility

ActionSwapBTV3

BT swaps — token/FW to/from BT

ActionSwapCTV3

CT swaps — synthesized via BT pool + mint/redeem

ActionAddRemoveLiqV3

Liquidity operations — dual, single-sided, keep-CT variants

ActionMiscV3

FW/BC minting, position exits, multicall, simulate

ActionBorrow

Fixed-rate borrow and repay via lending markets

ActionSimple

Gas-optimized operations using on-chain approximation

ActionCallbackV3

Flash-style swap callbacks from the market

ActionStorageV4

Admin — ownership transfer, selector management

CT swap synthesis

CT is not directly traded in the AMM (the pool only has BT and FW). CT swaps are synthesized using the flash-callback pattern:

Buy CT (FW → CT):

Sell CT (CT → FW): The reverse — buy BT from market with FW, pair with user's CT, redeem BT+CT for FW.

On-chain vs off-chain approximation

The router supports two modes for calculating swap amounts:

  • Off-chain hint (guessOffchain != 0) — Binary search using MarketApproxLibV2 with a hint provided by the caller. More gas-efficient for complex operations.

  • On-chain approximation (guessOffchain == 0) — Closed-form approximation using MarketApproxLibOnchain. Simpler code path, lower gas cost, used automatically when no hint is provided and no limit orders are present.

Last updated