Created
March 3, 2026 19:57
-
-
Save denniswon/eb560a373104299af2e2b1a249ebc878 to your computer and use it in GitHub Desktop.
Comprehensive Audit Report: Deploy Repo vs AVS Repo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| Comprehensive Audit Report: Deploy Repo vs AVS Repo | |
| CRITICAL: NetworkMode Destination Chain Mismatch | |
| Severity: BLOCKING — the gateway and operator will fail to start in production. | |
| The AVS repo's NetworkMode enum (crates/core/src/common/network.rs:41-47) defines destination chains that do NOT match the deploy repo's | |
| configuration: | |
| ┌─────────┬───────────────────────────────────────────────────────────────────┬─────────────────────────┬────────────────────┐ | |
| │ Network │ AVS NetworkMode::destination_chain_ids() │ Deploy dest_chain_ids │ Dockerfile configs │ | |
| ├─────────┼───────────────────────────────────────────────────────────────────┼─────────────────────────┼────────────────────┤ | |
| │ Testnet │ [11155420, 421614, 80002] (OP Sepolia, Arb Sepolia, Polygon Amoy) │ (84532,) (Base Sepolia) │ 84532, 8453 │ | |
| ├─────────┼───────────────────────────────────────────────────────────────────┼─────────────────────────┼────────────────────┤ | |
| │ Mainnet │ [10, 42161, 137] (Optimism, Arbitrum, Polygon) │ (8453,) (Base Mainnet) │ 84532, 8453 │ | |
| └─────────┴───────────────────────────────────────────────────────────────────┴─────────────────────────┴────────────────────┘ | |
| What breaks: When the gateway starts with --network testnet, MultiChainConfig::from_network() calls | |
| NetworkMode::Testnet.destination_chain_ids() → [11155420, 421614, 80002]. For each chain, it: | |
| 1. Looks for RPC_HTTP_URL_{chain_id} env var — not set (deploy only injects RPC_HTTP_URL_84532) | |
| 2. Looks for config file at /app/config/{chain_id}/gateway.toml — not present (Dockerfile only copies for 84532/8453) | |
| 3. Fails to build ChainService instances | |
| The same mismatch affects operators (also use --network). | |
| Resolution: Update NetworkMode in the AVS repo to include Base chains. The Dockerfile, deploy repo, environment JSONs, and CLAUDE.md all | |
| consistently reference Base Sepolia (84532) and Base Mainnet (8453) as the intended first destination chains. The current OP/Arb/Polygon | |
| entries appear to be placeholders from the design phase. | |
| Proposed change to crates/core/src/common/network.rs: | |
| // Before: | |
| Self::Testnet => vec![OPTIMISM_SEPOLIA, ARBITRUM_SEPOLIA, POLYGON_AMOY], | |
| Self::Mainnet => vec![OPTIMISM_MAINNET, ARBITRUM_ONE, POLYGON_MAINNET], | |
| // After (Phase 1: Base only): | |
| Self::Testnet => vec![BASE_SEPOLIA], | |
| Self::Mainnet => vec![BASE_MAINNET], | |
| This also requires adding the chain ID constants and updating is_testnet()/is_mainnet() classification functions to recognize 84532/8453, | |
| plus updating from_chain_id() tests. | |
| --- | |
| Verified Correct: CLI Arguments | |
| All 5 service types have correct CLI argument construction in the deploy repo: | |
| ┌───────────────┬──────────────────────────────────────────────────────────────┬─────────────────────────────────┬────────┐ | |
| │ Service │ Deploy command │ Binary expects │ Status │ | |
| ├───────────────┼──────────────────────────────────────────────────────────────┼─────────────────────────────────┼────────┤ | |
| │ Gateway │ --network {mode} --config-path ... --data-provider ... start │ Matches │ OK │ | |
| ├───────────────┼──────────────────────────────────────────────────────────────┼─────────────────────────────────┼────────┤ | |
| │ Operator │ --network {mode} --config-path ... --data-provider ... start │ Matches │ OK │ | |
| ├───────────────┼──────────────────────────────────────────────────────────────┼─────────────────────────────────┼────────┤ | |
| │ Challenger │ --chain-id {id} --config-path ... --data-provider ... start │ Matches │ OK │ | |
| ├───────────────┼──────────────────────────────────────────────────────────────┼─────────────────────────────────┼────────┤ | |
| │ Transporter │ --chain-id {id} --transporter-config ... start │ Matches │ OK │ | |
| ├───────────────┼──────────────────────────────────────────────────────────────┼─────────────────────────────────┼────────┤ | |
| │ Chain Watcher │ --chain-id {id} start │ Matches (no config file needed) │ OK │ | |
| └───────────────┴──────────────────────────────────────────────────────────────┴─────────────────────────────────┴────────┘ | |
| --- | |
| Verified Correct: Docker Targets & Image Tags | |
| ┌───────────────┬─────────────────────────┬───────────────────┬───────────────┬────────┐ | |
| │ Service │ Deploy image_tag_suffix │ Dockerfile target │ CI target │ Status │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Gateway │ gateway │ gateway │ gateway │ OK │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Operator │ operator │ operator │ operator │ OK │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Challenger │ challenger │ challenger │ challenger │ OK │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Transporter │ transporter │ transporter │ transporter │ OK │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Chain Watcher │ chain-watcher │ chain-watcher │ chain-watcher │ OK │ | |
| ├───────────────┼─────────────────────────┼───────────────────┼───────────────┼────────┤ | |
| │ Migration │ migration │ migration │ migration │ OK │ | |
| └───────────────┴─────────────────────────┴───────────────────┴───────────────┴────────┘ | |
| --- | |
| Verified Correct: Secret Key Names | |
| All SecretKeys in stacks/secrets_stack.py align with AVS binary expectations: | |
| ┌───────────────────────┬───────────────────────────────────────────────────┬───────────────────────────────────────┬────────┐ | |
| │ Secret │ Deploy key → env var │ Binary field │ Status │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Gateway signer │ GATEWAY__TASK_GENERATOR__SIGNER__PRIVATE_KEY │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Challenger signer │ CHALLENGER__SIGNER__PRIVATE_KEY │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Transporter signer │ TRANSPORTER__SIGNER__PRIVATE_KEY │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Operator signer │ OPERATOR{N}__SIGNER__PRIVATE_KEY │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Operator BLS │ OPERATOR{N}__BLS__PRIVATE_KEY │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Per-chain RPC HTTP │ RPC_HTTP_URL_{chain_id} │ rpc.rs resolution │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Per-chain RPC WS │ RPC_WS_URL_{chain_id} │ rpc.rs resolution │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Chain watcher Redis │ CHAIN_WATCHER__REDIS_URL ← DATA_CACHE_URL │ ChainWatcherConfig.redis_url │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Gateway watcher Redis │ GATEWAY__CHAIN_WATCHER_REDIS_URL ← DATA_CACHE_URL │ GatewayConfig.chain_watcher_redis_url │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ Data provider cache │ DATA_PROVIDER__DATA_CACHE_URL ← DATA_CACHE_URL │ ConfigLoader overlay │ OK │ | |
| ├───────────────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────┼────────┤ | |
| │ KMS key │ DATA_PROVIDER__KMS_RSA_KEY_ID │ ConfigLoader overlay │ OK │ | |
| └───────────────────────┴───────────────────────────────────────────────────┴───────────────────────────────────────┴────────┘ | |
| --- | |
| Verified Correct: RPC Injection Pattern | |
| The deploy repo uses a smart per-instance pattern: each per-chain service (challenger, chain watcher, transporter) is a separate ECS | |
| task. Chain-specific secrets are read from RPC_HTTP_URL_{chain_id} in Secrets Manager but injected as the generic RPC_HTTP_URL env var. | |
| Since each ECS task has its own environment, there's no collision. The binary then resolves via RPC_HTTP_URL_{chain_id} (not set) → | |
| fallback to RPC_HTTP_URL (set correctly). This works. | |
| --- | |
| Verified Correct: Chain Watcher Gateway URL | |
| CHAIN_WATCHER__GATEWAY_WATCHER_URL is constructed as http://gateway.{namespace}:{port}/watcher using service discovery. The gateway's | |
| Axum routes include /watcher (confirmed in crates/gateway/src/lib.rs). Port 8080 (SERVICE_PORTS.GATEWAY_HTTP) matches. | |
| --- | |
| Verified Correct: Security Group Rules | |
| The network_stack.py allows chain watcher → gateway ingress on port 8080, which is needed for the /watcher HTTP POST relay. | |
| --- | |
| Minor: Transporter Config Path | |
| Transporter uses --transporter-config /app/config/{dest_chain_id}/transporter.toml. The Dockerfile copies transporter.toml to | |
| /app/config/84532/transporter.toml and /app/config/8453/transporter.toml. This is correct for the current deploy config's | |
| transporter_dest_chain_ids = (84532,) / (8453,), but would need additional COPY lines if more destination chains are added. | |
| --- | |
| Summary | |
| ┌─────────────────────────────────────────┬──────────┬──────────────────────────────┐ | |
| │ Finding │ Severity │ Status │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ NetworkMode vs deploy chain ID mismatch │ CRITICAL │ Needs fix in AVS repo │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ CLI arguments │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ Docker targets / image tags │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ Secret key names │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ RPC injection pattern │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ Chain watcher gateway URL │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ Security groups │ - │ Correct │ | |
| ├─────────────────────────────────────────┼──────────┼──────────────────────────────┤ | |
| │ Config file paths │ - │ Correct (for current chains) │ | |
| └─────────────────────────────────────────┴──────────┴──────────────────────────────┘ | |
| The single blocking issue is the NetworkMode mismatch. The AVS repo's crates/core/src/common/network.rs needs to be updated so Testnet | |
| destinations include BASE_SEPOLIA (84532) and Mainnet destinations include BASE_MAINNET (8453), matching the deploy repo, Dockerfile, and | |
| environment configs. Would you like me to make that change? | |
| ★ Insight ───────────────────────────────────── | |
| - The deploy repo follows a "per-network for gateway/operator, per-chain for everything else" model. Gateway and operator use --network | |
| (one instance serves all chains), while challenger/transporter/chain-watcher each get one ECS task per chain via --chain-id. This is why | |
| the NetworkMode mismatch is critical — the gateway's chain topology is determined entirely by the binary's hardcoded NetworkMode enum, | |
| not by the deploy config. | |
| - The RPC injection pattern is clever: per-chain services read chain-specific secrets but inject them as generic env vars. Since each is | |
| a separate ECS task with its own env, this avoids needing the binary to know about chain-specific env var names for single-chain | |
| services. | |
| ───────────────────────────────────────────────── |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment