Methodology
DISCLAIMER // NFA // DYOR
This analysis is based on observations of the contract behavior. We are not smart contract security experts. This document aims to explain what the contract appears to do based on the code. It should not be considered a comprehensive security audit or financial advice. Always verify critical information independently and consult with blockchain security professionals for important decisions.
⊙ generated by robots | curated by humans
| METADATA | |
|---|---|
| Contract Address | 0x000000000000FB114709235f1ccBFfb925F600e4 (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-02-28 |
Overview
The zRouter contract was analyzed from verified Solidity source code (Exact Match on Etherscan). The source is a single 1,659-line file containing the main zRouter contract, a companion SafeExecutor contract, supporting library BalanceDeltaLibrary, and all necessary interfaces — no external imports.
The analysis began with Etherscan API v2 to fetch source code, ABI, and deployment metadata. The contract bytecode was fetched via cast using an authenticated RPC endpoint. Deployment context (block, timestamp, creator) was confirmed from the creation transaction. On-chain storage was read to confirm the current owner address.
Function selectors were derived using cast sig for all 29 functions. The source was read in full and analyzed in depth across all five AMM integration paths (V2, V3, V4, zAMM, Curve), the generic executor (snwap), the Lido staking helpers, and the .wei name registration flow. Assembly blocks were traced through manually. Transient Storage mechanics (EIP-1153) were analyzed for both the balance-passing pattern and the reentrancy lock.
The risk assessment focused on: who controls the contract, what arbitrary actions the owner/trusted callers can take, how user funds flow through the router, and what attack surfaces exist in the external dependency surface.
Thought Process
%%{init: {'theme': 'base'}}%%
mindmap
root((zRouter Analysis))
Phase 0: Obtain
Etherscan API v2
Source code verified
ABI extraction
Deployment metadata
cast bytecode fetch
Storage slot read
Phase 1: Discovery
Contract type: standalone
No proxy pattern
Owner: deployer EOA
SafeExecutor companion
5 AMM integrations
Lido staking
NameNFT integration
ERC-6909 support
Phase 2: Deep Dive
swapV2/V3/V4
swapVZ zAMM
swapCurve multi-hop
snwap generic executor
multicall delegatecall
EIP-1153 transient storage
V3 fallback callback
V4 unlockCallback
Permit / Permit2 helpers
Lido assembly paths
revealName flow
Phase 3: Risks
Unconstrained snwap executor
sweep no access control
Single owner no multisig
Lazy Curve approvals
tx.origin ownership
multicall delegatecall edge cases
V4 hookless-only
Zero amountLimit bypass
No public audit
Phase 4: Documentation
contract-analysis.md
functions.md
storage-layout.md
potential-risks.md
methodology.md
artifacts.md
Verification Guide
External Resources
| RESOURCE | PURPOSE |
|---|---|
| Etherscan — zRouter | Verified source code, ABI, creation tx |
| Etherscan — Creation TX | Deployment context — deployer, block, timestamp |
| Etherscan — SafeExecutor | Companion contract deployed in constructor |
| EIP-1153: Transient Storage | Mechanics of tstore/tload used throughout |
| Uniswap V4 Docs | unlock/callback architecture reference |
| Solady Library | Source of assembly-optimized token transfer helpers |
| Lido Developer Docs | stETH share mechanics used in exact-out Lido functions |
Commandline Tools
Tip
Commands below use cast from the Foundry Toolkit. To run the commands below, you must set the RPC URL environment variable:
Verify Contract Owner
# READ SLOT 0 — OWNER ADDRESS
cast storage 0x000000000000FB114709235f1ccBFfb925F600e4 0
# Expected: 0x0000000000000000000000001c0aa8ccd568d90d61659f060d1bfb1e6f855a20
# CALL safeExecutor() VIEW FUNCTION
cast call 0x000000000000FB114709235f1ccBFfb925F600e4 "safeExecutor()(address)"
# Expected: 0x25Fc36455aa30D012bbFB86f283975440D7Ee8Db
Verify Deployment Details
# FETCH DEPLOYMENT BLOCK
cast block 24440819
# INSPECT CREATION TRANSACTION
cast tx 0xb940d4ba4a6d058dc3ebde3900b51a675a4992f68e621dec48adba0290593d6b
# CHECK CONTRACT BYTECODE SIZE
cast code 0x000000000000FB114709235f1ccBFfb925F600e4 | wc -c
Verify Trust Mapping (Example)
# CHECK IF AN ADDRESS IS TRUSTED FOR EXECUTE()
# Replace <address> with the target to check (mapping slot 1)
cast call 0x000000000000FB114709235f1ccBFfb925F600e4 \
"trust(address,bool)()" \
<address> true
# Better: read the mapping directly via storage
Verify Function Selectors
# CONFIRM KEY FUNCTION SELECTORS
cast sig "swapV2(address,bool,address,address,uint256,uint256,uint256)"
# Expected: 0x6e0a4f98
cast sig "swapV3(address,bool,uint24,address,address,uint256,uint256,uint256)"
# Expected: 0xafeae12b
cast sig "swapV4(address,bool,uint24,int24,address,address,uint256,uint256,uint256)"
# Expected: 0x21c0dad2
cast sig "snwap(address,uint256,address,address,uint256,address,bytes)"
# Expected: 0x5f3bd1c8
cast sig "multicall(bytes[])"
# Expected: 0xac9650d8
cast sig "execute(address,uint256,bytes)"
# Expected: 0xb61d27f6
cast sig "sweep(address,uint256,uint256,address)"
# Expected: 0xcb019b84
Verify External Contract Addresses
# CONFIRM V4 POOL MANAGER ADDRESS MATCHES CONSTANT
# V4_POOL_MANAGER = 0x000000000004444c5dc75cB358380D2e3dE08A90
cast call 0x000000000004444c5dc75cB358380D2e3dE08A90 "owner()(address)" 2>/dev/null || echo "No owner() function"
# CONFIRM WETH ADDRESS
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 "symbol()(string)"
# Expected: WETH
# CONFIRM STETH ADDRESS
cast call 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 "symbol()(string)"
# Expected: stETH
# CONFIRM WSTETH ADDRESS
cast call 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 "symbol()(string)"
# Expected: wstETH
Token Cost Breakdown
| PHASE | DESCRIPTION | TOKENS |
|---|---|---|
| Phase 0 | Obtain the Contract | 5 tok |
| Phase 1 | Discovery & Understanding | 20 tok |
| Phase 2 | Deep Dive Analysis | 35 tok |
| Phase 3 | Risk & Trust Analysis | 10 tok |
| Phase 4 | Documentation Generation | 25 tok |
| TOTAL | Complete Contract Analysis | 95 tok |
Note: Token costs are estimates based on typical conversation lengths and complexity. Actual consumption may vary by ±10-15% depending on API responses, iterative refinement, and verification steps.