BotRadixBotRadixDocumentation

How to read BotRadix proxies

Follow router facets, module routes, CrossMargin and business controls without assuming EIP-1967.

BotRadix proxies and router do not use EIP-1967. The router also does not expose the EIP-2535 loupe. An explorer failing to detect a proxy, or an empty standard slot, does not prove that logic is fixed. Follow each family's own read functions.

Address, state and logic#

The host or proxy retains its address and state. When it delegates a function, code from another address executes against that state. An implementation can change without moving funds or changing the address the user sees.

To reconstruct a route, start from the official addresses, identify the function selector and query the contracts at the same block. Record the block number and hash, addresses, revisions and code hashes: mixing reads before and after an upgrade can produce a route that never existed.

An implementation ABI helps interpret delegated functions, but state reads and user transactions belong at the host address. Calling an implementation directly can revert or read different state. Identity reads explicitly directed to the implementation below are an exception.

Router: facets, dispatch kernel and modules#

The router combines a host table, extensions and a dispatch kernel that can prioritize the module registry. A facet is a piece of logic to which a function is routed.

ReadWhat it checks
routerLifecycle() on the routerReadiness, configuration seal, epoch, manifest and pending proposal
getFacetManifest() on the routerThe 17 manifest facets and their code hashes
facetForSelector(bytes4) on the routerThe host route for that selector; alone it does not reflect a registry override
dispatchLifecycle() on the routerAddress, code hash, revision and proposal of the dispatch kernel
moduleRegistryInfo() on the routerLookup mode, epoch, manifest, frozen state, delay and registry size
moduleRoute(bytes4) on the routerReported effective target for that selector, identity, revision and route source
TRADE_FACET(), then dexModule(0..12) on that facetInternal DEX components delegated to by the trading facet

With a kernel that enables the registry, a module route can take priority over the host route. In moduleRoute(), source 1 means a fixed or extension route, 2 the registry, and 3 a registry override of a fixed route; 0 means no effective route. A new selector may point to the hub in the host table: that hub reverts unless the required module route exists. A kernel that ignores the registry changes this interpretation, which is why dispatchLifecycle() and lookup mode also matter.

DexExtensionInstalled events help reconstruct extension changes, but a historical event does not prove the current route. Compare it with reads at the chosen block. Checking only the 17 facets omits extensions and module overrides.

CrossMargin: custom slot and modules#

On the CrossMargin proxy, implementation() returns the logic and lifecycle() exposes its seal, proposal, revisions and hashes. Its lifecycle storage root is:

text
bytes32(uint256(keccak256("botradix.cross.proxy.v1")) - 1)

This uses Ethereum Keccak-256, not SHA3-256. It is not the EIP-1967 slot. The first field is the implementation address; it shares a word with the sealing boolean, so do not interpret the entire word as an address. Prefer the read functions.

Next, call implementationModules() on the returned implementation address to identify its eight internal pieces. Account queries still belong at the proxy. Also call moduleRegistryInfo() and moduleRoute(selector) on the proxy to distinguish those pieces from module registry routes. Sealing the proxy and freezing every route or parameter are different questions.

Business proxies: separate control#

The oracle hub (PairForge), Registry, Automation and the Uniswap adapter use a separate control contract. Other business components, such as CrossVerifier, use the same family.

  1. Read BUSINESS_CONTROL() on the host.
  2. On the returned control, read current(), revision() and isSealed() for the logic, its revision and that path's seal.
  3. Read openPolicyLifecycle() on the host for the corresponding upgrade policy. A policy and business logic are different components.
  4. Where the host exposes the module registry, also read moduleRegistryInfo() and moduleRoute(selector) there. The main logic alone does not describe every function.

Reference example#

Documentation snapshot: 11 October 2026. These relationships provide orientation, not a substitute for a current read:

Starting pointReadReference result
Router 0x740E207d90ec9D82fce040F8DA0268dB761F364EdispatchLifecycle()BotradixDispatchKernelV2 0x95DC9EFbff26Acb8B9509d68dd73E712c4541093
CrossMargin 0x79ED1002F842DE2A9E25d353F2627206483b2b3Bimplementation()BotradixCrossMargin 0xc1030c90C644Df556c5fe311601B55B84387f6d7
PairForge 0x55Ec5A8DFEb6ab71BCAE98D833b4E1d96a6c871CBUSINESS_CONTROL()Control 0x255DdF4313FC5D547c3925748f30A8008676551f
That PairForge controlcurrent()BotradixPairForgeLogic 0x0744e9a3f4ad391414FA2d1443de2259bB1620e6

What verification establishes#

Verifying a host's source does not automatically verify its implementations, modules, policies or controls. A combined ABI also does not prove which route was active at a block. A complete check relates each component's address, bytecode, reproducible source, routes, authorities and seals.

Publication status at the reference date: source will be published jointly on BaseScan near closure. Read or write buttons are not assumed to exist already for every function. The mechanism above can also be inspected with tools holding the correct ABIs, without sending transactions.

See Security and contracts to interpret OPEN, the limits of AvisoPrevio and staged sealing, and Reproducible compilation to relate source and bytecode.

Last updated: 2026-10-12