Base 技術内核 深度レポート
日付: 2026-05-13
上流レポート:base/overview.md
本レポートの位置づけ: v1 の内容を重複させず、コード・コントラクト・オンチェーンデータ・SEC ファイリングの 4 つの深層レイヤーのみを掘り下げる
リポジトリ基準: 15 個のクローン済みリポジトリ、すべての参照パスはbase/repos/<repo>/<path>形式
本レポートは、Base チームが 2026-04-15 (推定) に op-stack fork から base/base Rust monorepo へ移行した後の最新コード、および base-deployments リポジトリの 2026-03-25 以前の完全な L1 デプロイ履歴に完全に基づいている。概览 ですでに書かれた「Base は OP Stack L2、Cannon は MIPS 仮想マシン、$12B TVL」といった総覧的叙述は二度と繰り返さない。本レポートは 8 つの具体的なサブ領域に踏み込み、各所で行番号までたどれるコード証拠、または etherscan で検証可能なオンチェーン証拠を提示する。
第一章 base/base Rust rollup 実装の完全解剖
1.1 リポジトリ全体の形態: Go モノリスから Rust ワークスペースへ
Base は 2026-04 に稀有な書き換えを完了させた。Optimism Bedrock の Go 実装 (op-node + op-geth 2 プロセス構成) を継承していたものから、単一の Rust ワークスペースへ、op-geth ではなく reth を、op-node ではなく kona-derive をベースに切り替えたのである。この移行の成果物が base/base リポジトリ (対応するオンチェーンは依然として Chain ID 8453 だが、クライアント実装は完全に入れ替わっている) である。
リポジトリのルートディレクトリ repos/base-base/Cargo.toml の 12-49 行目には、109 メンバー、約 1,400 個の .rs ソースファイルから成る巨大なワークスペースが宣言されている。統計:
$ find repos/base-base/crates -name Cargo.toml | wc -l
111
$ find repos/base-base -name "*.rs" -type f | wc -l
1374
repos/base-base/bin/ ディレクトリ配下には 16 個の独立した実行バイナリが生成される。これは展開する価値のあるリストである (Base の完全なランタイムにおけるすべてのプロセス境界を定義するからだ):
| バイナリ | 役割 | 従来 OP Stack における対応物 |
|---|---|---|
base |
完全な follow-node (validator モード) | op-node + op-geth |
based |
完全な sequencer/builder ノード | op-node (sequencer) + op-geth (block-building) |
consensus |
rollup-node のみのモード (EL なし) | op-node 単独モード |
node |
汎用 reth-fork ノードエントリ | op-geth |
builder |
Flashblocks-aware payload builder | Flashbots op-rbuilder |
batcher |
L1 バッチ提出器 | op-batcher |
proposer |
TEE+ZK output proposer | op-proposer + op-enclave |
challenger |
3 トラックフォールトプルーフチャレンジャー | op-challenger |
prover |
nitro-host / nitro-enclave / zk の 3 サブクレートを含む | op-program / op-enclave |
prover-registrar |
TEE 署名者の L1 登録器 | (Base 独自) |
audit-archiver |
builder に拒否された tx を S3 に転送 | (Base 独自) |
basectl |
ターミナル TUI 運用ツール | (Base 独自) |
ingress-rpc |
RPC アクセスエッジゲートウェイ | (インフラ) |
load-tester |
自製性能負荷テスト | (インフラ) |
mempool-rebroadcaster |
メモリプールブロードキャストプロキシ | (インフラ) |
websocket-proxy |
Flashblocks WebSocket マルチプレクシング | (インフラ) |
crates/ ディレクトリはタイプではなくドメイン別に整理されており、9 つのトップレベルグループがそれぞれ明確なサブシステムを担当する: batcher/ (5 サブクレート)、builder/ (3)、common/ (13)、consensus/ (14)、execution/ (20)、proof/ (15 + tee 5 + zk 4 + succinct 複数)、infra/ (インフラ)、utilities/、tools/。この細粒度の切り分けにより、ある箇所の変更がほぼ横方向に溢れ出すことがない—コンパイル時にサブシステム間のインターフェース境界が固定される。
リポジトリの CLAUDE.md (AGENTS.md のシンボリックリンク) には、非常に厳格な Rust スタイルのレッドラインがいくつか設定されており、これらの制約は実際に 1,374 個のすべての Rust ファイルに影響を及ぼしている:
All crates in the workspace should have a
base-prefix in their crate name (e.g.base-enclave,base-builder-core).
Alluseimports must be at the top of the file or the top of amodblock.
Use structured tracing instead of interpolated strings. Always use key=value fields for any dynamic data.
repos/base-base/Cargo.toml の 67-105 行目 ([workspace.lints.clippy]) には、約 30 個の clippy 警告レベルを error に引き上げるルールが定義されている。そのうち missing-const-for-fn、redundant-clone、clone-on-ref-ptr、option-if-let-else は warn に設定されているが、unused-must-use は直接 deny となっている。これは Base 内部の Rust エンジニアリング文化が「ゼロアロケーション + 明示的エラーハンドリング」に偏っていることを示しており、従来の op-geth Go コードの “err != nil { return err }” とは完全に異なる—Rust 側ではすべての失敗パスは thiserror 型エラーを経由し、panic-on-unwrap は禁止されている。
1.2 batcher サブシステム: L2 ブロックを L1 calldata または blob にエンコード
crates/batcher/ は Base が L2 ブロックを L1 データ可用性レイヤー (DA) にシリアライズするパイプライン全体である。5 つのサブクレートを含む:
batcher/core(753 LoCdriver.rs): 非同期スケジューラ、tokio::select!ループを実行batcher/encoder(2,158 LoCencoder.rs): 同期状態機械、L2 ブロックをフレームに変換batcher/comp(342 LoCchannel_out.rs+ 233 LoCbrotli.rs): 圧縮と channel 出力batcher/blobs(214 LoCencoder.rs+ 218 LoCdecoder.rs): EIP-4844 blob エンコーディングbatcher/source(623 LoChybrid.rs): L2 unsafe ブロックのソース
最も解体する価値があるのは repos/base-base/crates/batcher/blobs/src/encoder.rs の 26-62 行目で、Base がどのように L2 データを EIP-4844 blob に詰め込むかを精確に記述している:
pub struct BlobEncoder;
impl BlobEncoder {
/// Blob encoding version used by the Base blob codec.
pub const BLOB_ENCODING_VERSION: u8 = 0;
/// Maximum number of data bytes that fit in a single blob.
///
/// Each encoding round packs 4 field elements (128 blob bytes) into 127 data
/// bytes (4 x 31 payload bytes + 3 reassembled bytes). With 1024 rounds that
/// gives `127 * 1024 = 130_048` bytes, minus 4 bytes for the version +
/// 3-byte length header in field element 0.
pub const BLOB_MAX_DATA_SIZE: usize = PROTOCOL_BLOB_MAX_DATA_SIZE;
このコメントは一つの数字を暗示している: 各 EIP-4844 blob は 4 バイトヘッダーを差し引いた後で 130,044 バイト (≈ 127 KiB) の rollup データを運べる。Base は batcher 層において calldata と blob のどちらを選ぶかを crates/batcher/source/src/hybrid.rs で決定している—DA スロットラー (DaThrottle) がトリガーされると、driver は強制的に blob に切り替える:
repos/base-base/crates/batcher/core/src/driver.rs:67-72
/// When `true`, the driver toggles a blob-DA override on the pipeline
/// whenever DA-backlog throttling activates. Lifted from
/// [`BatchDriverConfig::force_blobs_when_throttling`].
force_blobs_when_throttling: bool,
これは Base が EIP-4844 への切り替え後も calldata 経路を保持する核心的な運用 trick である:通常時は blob、blob 市場が混雑すれば calldata にフォールバック、逆もまた然り。これを EIP-4844 稼働後の実データのコンテキストで見ると (IEEE 論文 arxiv 2405.03183 によれば、2024-03 Dencun 以降 L2 calldata 全体は 56.8% 低下、データ量は 116.8% 増加)、Base の batcher は長期にわたり 2 つの提出経路を同時にメンテナンスしている、単純に「blob にして後戻りなし」というわけではない。この背景には、米国上場企業である Coinbase が単一障害点に対する許容度が極めて低いことがある—コストは変動を受け入れられるが、停止は許されない。
crates/batcher/encoder/src/encoder.rs の 27-62 行目は、コアの同期状態機械 BatchEncoder を定義している:
pub struct BatchEncoder {
rollup_config: Arc<RollupConfig>,
config: EncoderConfig,
/// Current L1 head block number (for channel duration tracking).
l1_head: u64,
/// L2 blocks waiting to be encoded. Pruned when all their frames are confirmed.
blocks: VecDeque<BaseBlock>,
block_cursor: usize,
tip: B256,
current_channel: Option<OpenChannel>,
ready_channels: VecDeque<ReadyChannel>,
pending: HashMap<SubmissionId, PendingRef>,
...
span_accumulator: Vec<(SingleBatch, u64)>,
コメント内には特に引用に値する箇所がある (generator.rs:138-147):
When batcher’s max channel duration is big enough (e.g. 10m), the sequencer would send an avalanche of FCUs/getBlockByNumber on each batcher update (with 10m channel it’s ~800 FCUs at once). At such moment it can happen that the time b/w FCU and ensuing getPayload would be on the scale of ~2.5s. Therefore we should “remember” the payloads long enough to accommodate this corner-case (without it we are losing blocks).
このコメントは過去の production 事故への「謝罪」である: batcher の channel duration が長すぎる場合、L1 が channel 全体を確認した瞬間、sequencer は一度に約 800 個の ForkchoiceUpdated (FCU) を受信する。engine API がこの burst を処理するには約 2.5 秒かかり、その途中で payload のライフタイムを延長しないと失われてしまう。Base の解決策は extra_block_deadline (generator.rs:148)—payload の deadline を 5 秒延長してカバーする。これは非常に具体的で、現実の事故によって形作られたエンジニアリングパラメータであり、いかなる OP Stack 教科書にも載っていない。
1.3 builder サブシステムと Flashblocks の実装
1.3.1 トポロジー: builder は sequencer ではないが sequencer より重要
Base の builder は OP Stack 教科書の形態と異なる。教科書 OP Stack では sequencer (op-node + op-geth) が順序付けとブロック生成の両方を担う。Base はこれを分離した:
- sequencer (
crates/consensus/service/src/actors/sequencer/): いつブロックを出すか、どの L1 origin からブロックを出すかを決定 - builder (
bin/builder/+crates/builder/): このブロックの中身に何の tx を、どの順番で、いつサブブロック (flashblock) をブロードキャストするかを決定
バイナリ bin/builder/src/main.rs の 27-49 行目の起動シーケンスでは、builder は reth ExEx (Execution Extension) として BaseNodeRunner にインストールされている:
fn main {
base_cli_utils::init_common!;
base_reth_cli::init_reth!;
let cli = base_cli_utils::parse_cli!(BuilderCli);
cli.run(|builder, builder_args| async move {
let rollup_args = builder_args.rollup_args.clone;
let metering_provider: base_builder_core::SharedMeteringProvider =
Arc::new(builder_args.build_metering_store);
let builder_config = builder_args
.into_builder_config(Arc::clone(&metering_provider))
.expect("Failed to convert rollup args to builder config");
let mut runner = BaseNodeRunner::new(rollup_args)
.with_service_builder(FlashblocksServiceBuilder(builder_config));
runner.install_ext::<MeteringStoreExtension>(metering_provider);
runner.install_ext::<TxPoolRpcExtension>(TxPoolRpcConfig::default);
runner.install_ext::<BuilderApiExtension>;
...
この “ExEx-as-builder” パターンは reth チーム (Paradigm) が 2024-05 の Reth Execution Extensions で推進した中核パラダイムであり、Base が最大規模の真の本番採用者である—Paradigm Reth 2.0 は 2026-Q1 にリリースされ既に 1.7 Gigagas/s で動作しており、これが Base に builder 層で「ソフトウェアでハードウェアの絞り込みを加速する」余地を与えている。
1.3.2 Flashblocks 200ms サブブロックのコード証拠
Flashblocks (200ms サブブロック/preconfirmation) というコンセプトの源流は Flashbots の rollup-boost (仕様は github.com/flashbots/rollup-boost) であるが、Base はこの仕組み全体を自らの builder にネイティブ統合している。最も直接的なコード証拠は repos/base-base/crates/builder/core/src/config.rs の 173-178 行目にある:
/// Creates a new [`BuilderConfig`] suitable for testing with a randomized flashblocks port.
pub fn for_tests -> Self {
Self {
flashblocks_ws_addr: SocketAddr::new(Ipv4Addr::LOCALHOST.into, 0),
flashblocks_interval: Duration::from_millis(200),
flashblocks_leeway_time: Duration::from_millis(100),
block_time: Duration::from_secs(1),
..Self::default
}
}
これは Flashblocks の「200ms サブブロック」というマーケティング叙述に対して、コード内で見つけられる最も確かな数字である: flashblocks_interval = 200ms、flashblocks_leeway_time = 100ms、block_time = 1 秒 (注意: これはテストコンフィグであり、production は依然として 2 秒 block time、つまり各 2 秒ブロックは 10 個の 200ms flashblock を含む)。
Flashblock 自体のワイヤーフォーマットは repos/base-base/crates/common/flashblocks/src/payload.rs の 11-79 行目で精確に定義されている:
pub struct ExecutionPayloadFlashblockDeltaV1 {
pub state_root: B256,
pub receipts_root: B256,
pub logs_bloom: Bloom,
#[serde(with = "alloy_serde::quantity")]
pub gas_used: u64,
pub block_hash: B256,
pub transactions: Vec<Bytes>,
pub withdrawals: Vec<Withdrawal>,
pub withdrawals_root: B256,
#[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")]
pub blob_gas_used: Option<u64>,
}
pub struct FlashblocksPayloadV1 {
pub payload_id: PayloadId,
pub index: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub base: Option<ExecutionPayloadBaseV1>,
pub diff: ExecutionPayloadFlashblockDeltaV1,
pub metadata: Value,
}
base フィールドが Option であることに注目してほしい。index = 0 の最初の flashblock のみが base payload を持ち、後続の 9 個の flashblock は delta のみを送信する—これは Base が WebSocket 帯域を節約するための鍵となる設計である。各 flashblock は完全な state_root と receipts_root を含んでおり、受信側は 200ms 以内に state の変化を得られ、ブロック全体の封盤を待つ必要がない。
デコード経路では brotli 圧縮を使用する (crates/common/flashblocks/src/block.rs:14-15):
/// Maximum allowed decoded flashblock payload size, in bytes.
pub const MAX_DECOMPRESSED_FLASHBLOCK_BYTES: usize = 5 * 1024 * 1024;
各 flashblock の解凍後上限は 5 MB。2 秒ブロックあたり 10 個の flashblock を含む構成と組み合わせると、Base の builder は最も極端な状況下では毎秒 25 MB のデータをブロードキャストする必要がある—これがなぜ crates/builder/publish/src/broadcast.rs が 517 行に及び、独立した websocket-proxy バイナリ (crates/infra/websocket-proxy/) に依存してマルチプレクシングを行うかの理由である。
1.3.3 Flashblocks と builder 状態機械
crates/builder/core/src/flashblocks/generator.rs の 504-522 行目は payload job のデッドラインロジックを定義している:
fn job_deadline(unix_timestamp_secs: u64) -> std::time::Duration {
let unix_now = match SystemTime::now.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs,
Err(e) => {
warn!(error = %e, "System clock went backward, returning zero deadline");
return Duration::ZERO;
}
};
let duration_until = unix_timestamp_secs.saturating_sub(unix_now);
if duration_until == 0 {
Duration::from_secs(1)
} else {
Duration::from_secs(duration_until)
}
}
builder の BlockPayloadJob::poll (generator.rs:338-356) は stateful future であり、各 poll 時に以下を確認する:
- デッドラインが到達したか → すべての build をキャンセル
- 外部からキャンセルされたか (新しい FCU が到着) → yield する
- それ以外は pending を継続
crates/builder/core/src/flashblocks/payload.rs は 1,425 行に及び、Base builder の最も核となる「flashblock をどう生成するか」のロジックである。600-720 行目のループが実際のサブブロック生成である:
let payload_transaction_simulation_time = tx_execution_start_time.elapsed;
BuilderMetrics::payload_transaction_simulation_duration
.record(payload_transaction_simulation_time);
...
let build_result = build_block(state, ctx, info, ctx.attributes.no_tx_pool);
...
match build_result {
Err(err) => {
BuilderMetrics::invalid_built_blocks_count.increment(1);
Err(err).wrap_err("failed to build payload")
}
Ok((new_payload, mut fb_payload)) => {
fb_payload.index = flashblock_index;
fb_payload.base = None;
// Synchronized check + publish.
let (cancelled, flashblock_byte_size) = {
let _guard = publish_guard.lock;
if block_cancel.is_cancelled {
(true, 0)
} else {
let size = self
.ws_pub
.publish(&fb_payload, ctx.block_number, flashblock_index)
.wrap_err("failed to publish flashblock via websocket")?;
(false, size)
}
};
ここには展開する価値のあるディテールがいくつかある:
publish_guardmutex: ブロック生成キャンセル (cancel) と publish の間でMutex<>で排他制御し、既に無効化された flashblock を送出しないことを保証する。これは Base builder が独自に作った「発行即発効」の atomic セマンティクスで、下流の RPC サービスが永遠に落盤しない tx を見ることを防ぐ。fb_payload.base = None: 2 つ目以降の flashblock では base payload を明示的にクリアし、回線帯域を削減する。flashblock_byte_sizeメトリクス: 各 flashblock 個別にバイト数と tx 数を計測する。これにより運用チームは「どの flashblock が空で、どの flashblock が満杯か」という非常に細かい次元を得られる。
1.3.4 Flashblock 内 tx 選択アルゴリズム
crates/builder/core/src/flashblocks/best_txs.rs の 215-261 行目は非常に subtle な tx 選択戦略を定義している。コメントには直接 === FLASHBLOCK 1 === と === FLASHBLOCK 2 === のテストケースが書かれている:
// === FLASHBLOCK 1 ===
let mut iterator = BestFlashblocksTxs::new(
BestPayloadTransactions::new(pool.best),
test_rejection_cache,
);
// Simulate: Flashblock 1 starts building
let first = iterator.next.unwrap;
assert_eq!(first.sender, sender_a, "First should be TX_A (1 gwei)");
// TX_B and TX_C arrive late, but we have already yielded lower-priority transactions
// from the iterator, so these do not immediately get added to the best txns
pool.add_transaction(Arc::new(f.validated(tx_b.clone)), 0);
pool.add_transaction(Arc::new(f.validated(tx_c.clone)), 0);
assert_eq!(iterator.next, None);
// Simulate: flashblock 1 is complete after TX_A was executed
iterator.mark_committed(&[*tx_a.hash]);
// === FLASHBLOCK 2 ===
iterator.refresh_iterator(BestPayloadTransactions::new(pool.best));
// Now, theoretically, TX_A has already been executed, so
// TX_B should be the best txn and TX_C the second best
このテストは重要な MEV 幾何学を明らかにする:flashblock の境界は 200ms 間隔の「再順序付けポイント」に相当する。flashblock 1 がロックされた後にメンプールに到着した高価な tx (TX_B 100 gwei、TX_C 10 gwei) は、既に flashblock 1 に入っている低価格 tx (TX_A 1 gwei) を「巻き戻して」追い出すことはないが、flashblock 2 では直ちに取り込まれ、priority fee 順にソートされる。
これがちょうど Bitcoin Ethereum News の報道 で記述された、Jesse Pollak 自身の creator-coin がリリースされた際に 2 人の sniper に $1.3M を抜き取られたコアメカニズムである—彼らは flashblock N のメンプール状態を予見できる状態で、flashblock N+1 で巨額の priority fee を投入し前列を奪う。Base 自身の builder コードは全く先回り (front-running) しないが、200ms のサブブロック可視性によって第三者の sniper には、2 秒 block-only 時代には存在しなかった新しいメンプール観察ウィンドウが与えられた。
1.4 batcher / builder / sequencer の境界
これらをまとめると、Base の完全な L2 ブロックライフサイクルは以下の通り:
t=0 sequencer が block N (timestamp = unix_now) を出すと決定
↓ engine_forkchoiceUpdatedV3 (FCU)
t=0 builder が FCU を受信し、BlockPayloadJob を起動
↓ mempool から tx を取得し、実行
t=200ms builder が flashblock 0 を送出 (base payload + 第 1 バッチ tx 含む)
t=400ms builder が flashblock 1 を送出 (delta のみ + 第 2 バッチ tx)
...
t=2000ms builder が flashblock 9 を送出、同時に engine_getPayloadV3 で完全な block を取得
↓ sequencer が完全な block を consensus 層 P2P gossip に push
↓ batcher が複数 block を蓄積した後、frame に圧縮し channel に詰める
t≈2-30s batcher が channel を EIP-4844 blob 経由で L1 に提出
↓ L1 は 12 秒ごとに 1 slot、平均 6 秒でブロック組み込み待ち
t≈30s L1 ブロックがこの batch を含み、base-node-validator のリプレイをトリガー
↓ validator が L1 から L2 block N (safe head) を derive
t≈12 分後 L1 ブロックが finalized、L2 block N が finalized 状態に
ここには記憶に値する「具体的な数字」がいくつかある:
- batcher のデフォルト
channel_timeoutは 300 秒 (crates/common/genesis/src/rollup.rs:GRANITE_CHANNEL_TIMEOUT)、つまり 300 秒以内は channel を強制クローズしない - しかし driver の設定では
block_time = 2sなので、1 channel に理論上 150 ブロックを詰められる - 実際の Base メインネットでは DA コストを抑えるため、channel は通常 30-60 秒で提出される
1.5 proof サブシステムのワークスペース形態
crates/proof/ は base/base コード全体の中で最も大きく、最も複雑な部分であり、全体のコード量の約 30% を占める。サブクレートリスト (repos/base-base/Cargo.toml:24-50) は、Base が TEE と ZK の 2 つの経路を同時に賭けていることを明らかにする:
crates/proof/mpt - Merkle-Patricia Trie 実装
crates/proof/proof - 高レベル SDK
crates/proof/driver - フォールトプルーフ driver
crates/proof/client - クライアント
crates/proof/executor - 状態実行器 (ステートレス)
crates/proof/preimage - preimage oracle
crates/proof/primitives - Proposal / ProofJournal / ProofResult の 3 つの共有型
crates/proof/host - host 側
crates/proof/tee/nitro-host ← AWS Nitro ホスト側
crates/proof/tee/nitro-enclave ← AWS Nitro enclave 内部 (vsock listener + NSM)
crates/proof/tee/registrar ← TEE 署名者のオンチェーン登録
crates/proof/tee/nitro-verifier ← Nitro 証明書チェーン + X.509 検証
crates/proof/tee/nitro-attestation-prover ← attestation を ZK proof に変換 (Boundless 経由)
crates/proof/zk/client / db / outbox / service ← ZK ホスト側
crates/proof/zk/service/src/backends/op_succinct/cluster.rs ← SP1 クラスター接続
crates/proof/contracts - L1 コントラクト binding (DisputeGameFactory, AggregateVerifier, AnchorStateRegistry)
crates/proof/rpc - challenger / proposer 用 RPC trait
crates/proof/proposer - L1 output proposer
crates/proof/challenge - challenger driver
crates/proof/succinct/utils - SP1 ユーティリティ
crates/proof/succinct/validity - 検証ロジック
この節では総図のみを示し、具体的なフォールトプルーフ 3 トラック投票は第二章に譲る。
第二章 3 トラックフォールトプルーフシステム深掘り
2.1 3 トラック並列の本当の意味
概览 では、Base が 2024-10-30 に「Stage 1 fault proofs」を稼働し、OP Stack の Cannon (MIPS VM) で仲裁することを言及していた。しかし v1 で明らかにしていなかったのは、Base が 2025-2026 期に Cannon 単一仲裁を完全に放棄し、3 トラック並列の TEE + ZK + (legacy permissioned) マルチシグ 投票モデルに転換したことであり、最終的には 2026-05-13 (本レポート執筆日のその週) の Base Azul アップグレードで正式に発効した。
crates/proof/contracts/src/aggregate_verifier.rs の 22-110 行目の IAggregateVerifier インターフェースが、この新モデルの Solidity レベルの証拠である。重要なメソッド:
function teeProver external view returns (address); // ← TEE 提出者アドレス
function zkProver external view returns (address); // ← ZK 提出者アドレス
function rootClaim external pure returns (bytes32); // ← output root
function intermediateOutputRoots external view returns (bytes memory);
function intermediateOutputRoot(uint256 index) external view returns (bytes32);
function nullify(
bytes calldata proofBytes,
uint256 intermediateRootIndex,
bytes32 intermediateRootToProve
) external;
function challenge(
bytes calldata proofBytes,
uint256 intermediateRootIndex,
bytes32 intermediateRootToProve
) external;
コメントには明記されている:
The first byte of
proofBytesis the proof type discriminator:0for TEE,1for ZK.
これが 3 トラック構造のコアである—dispute game はもはや単一の証明型に紐付けられず、2 種類の証明 (TEE = 0, ZK = 1) を受け付け、nullify と challenge 関数は最初のバイトで区別する。下記の BLOCK_INTERVAL と INTERMEDIATE_BLOCK_INTERVAL の露出と合わせると、Base の dispute game は本質的にダブルプルーフのチェックポイントチェーンである: INTERMEDIATE_BLOCK_INTERVAL (コードのデフォルト値は 512、crates/proof/proposer/src/driver.rs:62 参照) 個の L2 ブロックごとに中間 output root を設置し、いずれかの root が TEE または ZK によって偽造であると証明されれば、game 全体が nullify される。
2.2 TEE 側: AWS Nitro Enclave の完全経路
2.2.1 op-enclave の進化と base-op-enclave リポジトリ
repos/base-op-enclave/README.md の 6-9 行目に明確に書かれている:
op-enclave is a relatively small modification to the op-stack that proves state transitions in an AWS Nitro Enclave, and submits the resulting state roots to the L1 chain. This removes the need for the 7-day challenge period, and allows for immediate withdrawals.
これは Base が 2024-2025 期に独立してメンテナンスしていた fork である。その op-enclave/ サブディレクトリは Go プログラムであり、AWS Nitro Enclave (KVM ベースのハードウェア隔離環境) の内部で動作するよう設計されている。特徴:
- stateless: enclave は自身で state を永続化せず、すべての L2 chain data は L1 からリプレイ
- deterministic: 各 enclave image は SHA-384 measurement (PCR0) を持ち、PCR0 が SystemConfigGlobal に登録された値と一致する enclave のみが output root に署名できる
- attestation-driven: 提出される output root は Nitro attestation を伴い、L1 コントラクトがこの attestation を検証した後に受理する
repos/base-op-enclave/README.md の Architecture 部分には一文がまとまっている:
Because the output root is accepted based on the TEE attestation (and the trusted signer check), withdrawals can be processed almost instantly.
これが Base がずっと「高速出金」(実際には約 1-2 時間、OP Mainnet の 7 日よりはるかに短い) を宣伝できる根拠である。
2.2.2 base-base リポジトリ内の enclave 書き換え
2026 年の base/base monorepo になり、op-enclave は完全に Rust で書き換えられ、さらに細分化された。crates/proof/tee/nitro-enclave/src/server.rs の 1-50 行目が新版のエントリポイントである:
/// Enclave server — manages keys, attestation, signing, and proof execution.
use std::sync::LazyLock;
use alloy_primitives::{Address, B256, Bytes, keccak256, map::HashMap};
use alloy_signer_local::PrivateKeySigner;
use base_common_chains::ChainConfig;
use base_common_evm::BaseEvmFactory;
use base_common_genesis::RollupConfig;
use base_proof::BootInfo;
use base_proof_client::Prologue;
use base_proof_preimage::PreimageKey;
use base_proof_primitives::{PerChainConfig, ProofJournal, ProofResult, Proposal};
use tracing::info;
...
/// PCR0 is a SHA-384 hash (48 bytes) per the AWS Nitro Enclaves specification.
const PCR0_LENGTH: usize = 48;
Server::new (server.rs:67-80) は起動時に:
1. NSM (Nitro Security Module) セッションを開く
2. PCR0 (48 バイトの SHA-384) を読み取る
3. ハードウェア RNG で ECDSA secp256k1 秘密鍵を生成 (永遠に enclave を離れない)
4. PCR0 を keccak256 した値を tee_image_hash として公開 (この hash が L1 上の TEEProverRegistry 登録時に検証される鍵となる)
nitro-enclave モジュール全体は 9 ファイル、合計 1,514 行の Rust から成り、完全に隔離された KVM ゲスト内で動作する。host との通信は vsock (Linux 仮想ソケット) 経由 (nitro-host/src/vsock.rs:127 行)、ネットワークには一切触れない。
2.2.3 base/base の prover-registrar: TEE を L1 に登録
crates/proof/tee/registrar/src/driver.rs (3,165 行、base/base リポジトリ全体で最長の Rust ファイル) は、完全な「TEE 署名者のオンチェーン登録」driver を実装している。コメントの冒頭:
Discovers prover instances, checks on-chain registration status, generates ZK proofs for unregistered signers, and submits registration transactions to L1 via the [
TxManager]. Also detects orphaned on-chain signers (those no longer backed by a healthy instance) and deregisters them.
これは Base 独自のコンポーネントであり、OP Stack 教科書には対応物が全く存在しない。ワークフローは:
- 発見 (
InstanceDiscovery): AWS API 経由で enclave を動かしているすべての EC2 インスタンスを見つけ、各インスタンスは 1 つの TEE 署名者に対応 - ヘルスチェック (
InstanceHealthStatus): ALB ヘルスチェック経由でインスタンスの生存を確認 - ZK 証明の生成 (
AttestationProofProvider): Nitro attestation (X.509 証明書チェーン + PCR0) を SP1 zk proof に変換、この処理は Boundless ネットワーク経由で約 20 分かかる - オンチェーン登録 (
TxManager): (TEE signer address, ZK proof of attestation) を L1TEEProverRegistryコントラクトに書き込む
driver.rs の 29-31 行目:
/// Default maximum number of instances processed concurrently.
///
/// Each instance may trigger a ~20-minute Boundless proof generation, so
/// limiting concurrency prevents overwhelming the proof service and keeps
/// nonce management tractable.
pub const DEFAULT_MAX_CONCURRENCY: usize = 4;
20 分で 1 回の attestation ZK proof × 最大 4 並列 → TEE クラスター 1 回の稼働/ローテーションには約数時間を要する
これが Base が op-enclave/Nitro TEE 経路における実際の運用コストである。
2.2.4 PCR0 と enclave image のロック
repos/base-op-enclave/tools/ 配下には完全な PCR0 検証ツールチェーンがある。Nitro Enclave は PCR0 という SHA-384 hash を使って enclave バイナリ + カーネル + 設定の全体 measurement をロックしており、バイト単位の修正があれば PCR0 は変わる。Base はアップグレードごとに PCR0 を明示的に SystemConfigGlobal コントラクトに登録し、enclave が output root を提出する際にコントラクトが attestation 内の PCR0 が allowlist 内にあることを検証し、そうでなければ reject する。
この「image hash = 権限」モデルには深い特徴がある:いったん PCR0 が attacker に置き換えられても、過去に署名されたすべての output root は依然有効である—コントラクトは「署名時に PCR0 が allowlist にあったか」だけを検証するからだ。だからこそ、Base は同期的な ZK 証明をクロスチェックとして持つ必要がある。
2.3 ZK 側: OP Succinct SP1 クラスター
2.3.1 Cannon (MIPS) から Kona (Rust) を経て SP1 (zkVM) へ
歴史的に OP Stack のフォールトプルーフプログラムは Go で書かれた op-program であり、Cannon (MIPS32 インタープリタ) で動作していた。repos/optimism-monorepo/cannon/README.md の 10-16 行目はそのまま要約している:
Cannon is an onchain MIPS instruction emulator. Cannon supports EVM-equivalent fault proofs by enabling Geth to run onchain, one instruction at a time, as part of an interactive dispute game.
- It’s Go code
- …that runs an EVM
- …emulating a MIPS machine
- …running compiled Go code
- …that runs an EVM
これはマトリョーシカである—Go コードが MIPS にコンパイルされ、MIPS が EVM 内で解釈され、解釈されたコードがまた EVM を走らせる。このアーキテクチャの代償は膨大な step count (完全なフォールトプルーフゲームで約 1-10 億の MIPS 命令) と長大な二分探索時間である。
repos/optimism-monorepo/op-program/README.md の最初の文はこうである:
Deprecated: op-program is deprecated and being replaced by kona-client.
Existing deployments will be supported until the Karst hardfork, at which point migration to kona-client is required.
Kona は OP Stack の Rust 書き換え (rust/kona/) であり、コア目標は OP Stack の state transition function (STF) を、任意の zkVM (SP1/Risc0/Jolt) で直接証明可能な純粋な Rust プログラムとして書くことである。rust/kona/README.md の 31-37 行目:
Originally a suite of portable implementations of the OP Stack rollup state transition, Kona has been extended to be the monorepo for OP Stack types, components, and services built in Rust. Kona provides an ecosystem of extensible, low-level crates that compose into components and services required for the OP Stack.
Succinct Labs は Kona を SP1 (RISC-V ベースの zkVM) と組み合わせ、OP Succinct を構築した—OP Stack 全体にゼロ知識 validity proof を出力できるシステムである。キーポイントは:
- Kona は決定的、IO 非依存の Rust プログラムであり、zkVM に適している
- SP1 は LLVM RISC-V backend + STARK 証明系を用いた zkVM で、1 回の証明コストは約 $1-2、レイテンシは約 30-60 分
- 集約 (aggregation) によって、数十の range proof を 1 つの succinct proof に集約して L1 に提出できる
2.3.2 Base がどう op-succinct と接続するか
crates/proof/zk/service/src/backends/op_succinct/cluster.rs の 1-30 行目は、Base が op-succinct の上にラップした層を示している:
//! Succinct proving backend using the SP1 cluster.
use std::{fmt, time::SystemTime};
use async_trait::async_trait;
use base_proof_succinct_client_utils::client::DEFAULT_INTERMEDIATE_ROOT_INTERVAL;
use base_proof_succinct_elfs::{AGGREGATION_ELF, RANGE_ELF_EMBEDDED};
use base_proof_succinct_host_utils::get_agg_proof_stdin;
use base_zk_client::ProveBlockRequest;
use base_zk_db::{
CreateProofSession, ProofRequest, ProofRequestRepo, ProofSession, ProofStatus, ProofType,
SessionStatus as DbSessionStatus, SessionType, UpdateProofSession, UpdateReceipt,
};
use serde_json::json;
use sp1_cluster_common::proto::{
ExecutionFailureCause, ExecutionStatus, ProofRequest as ClusterProtoProofRequest,
ProofRequestStatus,
};
use sp1_cluster_utils::{ClusterElf, ProofRequestConfig, create_request};
use sp1_prover_types::{Artifact, ArtifactClient as _, ArtifactType};
特に重要なのはこの 2 行である:
use base_proof_succinct_elfs::{AGGREGATION_ELF, RANGE_ELF_EMBEDDED};
AGGREGATION_ELF と RANGE_ELF_EMBEDDED は 2 つの RISC-V ELF ファイルで、Base の prover バイナリにコンパイル組み込まれている。”Range ELF” は連続した N 個の L2 block の STF が合法であることを証明する役割を担い、”Aggregation ELF” は複数の range proof を 1 つの最終 proof に集約する。
crates/proof/succinct/validity/src/proposer.rs は SP1 クラスターと L1 の通信のブリッジである。9-30 行目の import が依存関係グラフ全体を明らかにする:
use base_proof_succinct_host_utils::{
DisputeGameFactory::DisputeGameFactoryInstance as DisputeGameFactoryContract,
OPSuccinctL2OutputOracle::OPSuccinctL2OutputOracleInstance as OPSuccinctL2OOContract,
fetcher::OPSuccinctDataFetcher,
host::OPSuccinctHost,
metrics::MetricsGauge,
network::{determine_network_mode, get_network_signer},
};
use sp1_sdk::{
Elf, HashableKey, NetworkProver, Prover, ProverClient, ProvingKey, SP1Proof,
SP1ProofWithPublicValues,
network::{
NetworkMode,
proto::types::{ExecutionStatus, FulfillmentStatus},
},
};
OPSuccinctL2OutputOracle に注目—これは Succinct チームが OP Stack の L2OutputOracle から fork し、fault dispute game ではなく SP1 proof を受け入れる版である。Base は Azul アップグレードで DisputeGameFactory を直接 OPSuccinctL2OutputOracle に置換しなかった。代わりに ZK を dispute game の一つの prover タイプとして既存の dispute game framework に注入した (つまり 2.1 節で記述された proofBytes[0] = 1 が ZK を表すこと)。これは非常に conservative な移行選択であり、The Block の報道 で語られている「ダブルプルーフが同時に発効」と完全に一致する。
2.4 challenger: 3 トラック投票の実行者
crates/proof/challenge/src/driver.rs (941 行) は Base 独自の challenger 実装であり、repos/optimism-monorepo/op-challenger/ (Go 版) とは完全に独立している。crates/proof/challenge/README.md がその責務を要約している:
- Scanner: Scans the
DisputeGameFactoryforIN_PROGRESSdispute games and classifies each into aGameCategory(InvalidTeeProposal,FraudulentZkChallenge, orInvalidZkProposal) based on prover state.- Validator: Verifies final and intermediate output roots for each
CandidateGameby fetching L2 block headers andL2ToL1MessagePasserstorage proofs, recomputing expected roots viaOutputRoot, and comparing them against onchain claims.- Pending: Tracks in-flight proof sessions through a
ProofPhaselifecycle (AwaitingProof→ReadyToSubmitorNeedsRetry).- Submitter: Submits dispute transactions onchain (
nullify/challenge) for invalid games.- Bond: Multi-phase bond credit claim lifecycle (
NeedsResolve→NeedsUnlock→AwaitingDelay→NeedsWithdraw).
GameCategory という enum は 3 種類の攻撃シナリオを示唆している:
- InvalidTeeProposal: TEE が誤った output root を提出した (PCR0 に悪意あるコードが注入されたか、enclave が破壊された)。ZK が
nullifyを提出して覆す必要がある - FraudulentZkChallenge: ZK が誤った「TEE に反対する」証明を提出した (理論的には ZK proof の検証失敗で reject されるが、集約 proof のある境界ケースで通過しうる)。2 度目の ZK で覆す必要がある
- InvalidZkProposal: ZK が能動的に誤りを提出した。TEE で覆す (またはより新しい ZK で覆す)
Base はメインネット上で同時に (少なくとも) TEE prover + ZK prover + Base チーム独自の challenger + Optimism Foundation の challenger を稼働させている。どの一方でも invalid game を発見すればオンチェーンで nullify できる。
2.5 オンチェーンの実データ: 2025-03 と 2025-04 の 2 回のフォールトプルーフアップグレード
repos/base-deployments/mainnet/2025-03-05-upgrade-fault-proofs/addresses.json:
{
"faultDisputeGame": "0xfe884b822eddb5864e86626e088120c73c0a4364",
"permissionedDisputeGame": "0x8cf5972cedf63b099406b3e7da81566885453d8e"
}
README.md の 3 行目:
Status: EXECUTED
これは Base メインネットが 2025-03-05 に実際にデプロイした fault dispute game アップグレードであり、etherscan のトランザクション 0xac0db12a427a31ccbaf4a154cf6d5acf0b83c791a4bd7f93a54c9b150b9aa668 で検証可能。
その後 2025-04-23 のもう 1 回のアップグレード repos/base-deployments/mainnet/2025-04-23-upgrade-fault-proofs/README.md:
Upgrade 15 - Fault Proof Upgrades for Isthmus
Status: EXECUTED
このアップグレードは Isthmus ハードフォークと同時に実行され、FaultDisputeGame と PermissionedDisputeGame を再デプロイして、Isthmus で新たに導入された EIP-2935 履歴 block hash コントラクトに対応させた (crates/consensus/upgrades/src/isthmus.rs:30-34 参照):
/// EIP-2935 From Address
pub const EIP2935_FROM: Address = address!("3462413Af4609098e1E27A490f554f260213D685");
/// The new L1 Block Address
pub const NEW_L1_BLOCK: Address = address!("ff256497d61dcd71a9e9ff43967c13fde1f72d12");
2025-11-21 の U17 Jovian アップグレード (repos/base-deployments/mainnet/2025-11-21-u17-jovian-upgrade/README.md):
The Jovian hardfork is a proposed network upgrade for OP Stack chains, which brings several improvements to the way rollup fees are calculated as well as performing a maintenance update to the fault proof virtual machine.
Status: EXECUTED
このアップグレードはフォールトプルーフ VM 自体に手を入れている。crates/consensus/upgrades/src/jovian.rs:18-50 は Jovian で導入された 2 つの新しい predeploy を公開する:
pub struct Jovian;
impl Jovian {
upgrade_source_fn!(
deploy_l1_block_source,
"Jovian: L1 Block Deployment"
);
upgrade_source_fn!(
l1_block_proxy_update,
"Jovian: L1 Block Proxy Update"
);
upgrade_source_fn!(
gas_price_oracle,
"Jovian: Gas Price Oracle Deployment"
);
pub fn l1_block_address -> Address {
Deployers::JOVIAN_L1_BLOCK.create(0)
}
pub fn gas_price_oracle_address -> Address {
Deployers::JOVIAN_GAS_PRICE_ORACLE.create(0)
}
各ハードフォークでは L1Block と GasPriceOracle という 2 つの predeploy が再デプロイされる。これは OP Stack に一貫したアップグレードパターンであり、deposit tx の source hash (upgrade_source_fn マクロ) によってアップグレード行為が L2 derivation 期に決定的にリプレイされる。
第三章 Sequencer 内部メカニズム
3.1 sequencer actor: 単一 sequencer だが software-defined
crates/consensus/service/src/actors/sequencer/ は Base sequencer の完全なコードである。モジュールリスト (mod.rs):
mod build; // PayloadBuilder, UnsealedPayloadHandle
mod config; // SequencerConfig
mod origin_selector; // L1OriginSelector, DelayedL1OriginSelectorProvider
mod recovery; // RecoveryModeGuard
mod seal; // PayloadSealer, SealState, SealStepError
mod ticker; // ScheduledTicker
mod pool; // PoolActivation
mod actor; // PendingStopSender, SequencerActor
mod admin_api_impl; // SequencerAdminQuery
mod metrics;
mod error;
mod conductor; // Conductor, ConductorClient, ConductorError
mod engine_client;
注目に値するのは conductor モジュールである。これは OP Stack の op-conductor の Rust 等価物であり、複数の sequencer 候補者(Coinbase は理論上、現時点で複数の sequencer インスタンスを稼働させているが、active なのは 1 つのみ)の間で primary/standby 切り替えを行う責任を持つ。これは v1 レポートで指摘された「Stage 1 にまだ何が足りないか」リストの “sequencer decentralization” 項目の下流における配置であり、コード層では既に conductor abstraction が実装されており、政策層の承認を待っている状態である。
3.2 sequencer と builder の実際のハンドシェイク
crates/consensus/service/README.md で RollupNode::start の起動シーケンスを記述している部分に非常に情報量の多い一節がある:
Third, the engine actor is constructed. It wraps a
BaseEngineClienttogether with anEnginetask queue, anEngineProcessorthat holds the bootstrap logic and main processing loop, and anEngineRpcProcessorthat handles concurrent RPC queries behind a semaphore of size 16.In Sequencer mode the engine bootstraps differently — either with a conductor-follower probe using zeroed safe/finalized heads, or as an active sequencer that probes with real heads or resets at genesis — and additionally publishes an
unsafe_head_txwatch channel that the sequencer actor reads to know the current building parent.
ここでの鍵は unsafe_head_tx watch channel である: sequencer は unsafe_head のブロードキャストを watch することで、次のブロックを誰の上に build すべきかを知り、gossip_payload_tx を通じて自ら build したブロックを P2P に push する。
そして builder (別プロセスあるいは別マシンで稼働) は engine API 経由で sequencer の FCU を受信し、200ms のリズムで flashblock を生成する。
3.3 batcher のリズム: 実際の L1 提出頻度
crates/batcher/core/src/driver.rs:69-78:
/// Whether block ingestion is currently stopped (paused via admin or `--stopped` flag).
stopped: bool,
/// Admin command channel, wired in via [`Self::with_admin_rx`].
admin_rx: Option<mpsc::Receiver<AdminCommand>>,
/// When `true`, the driver toggles a blob-DA override on the pipeline
/// whenever DA-backlog throttling activates.
force_blobs_when_throttling: bool,
crates/batcher/core/src/driver.rs:113 は STEP_BUDGET = 128 を設定—1 ラウンドの select ループで最大同期 128 ステップのエンコードを実行し、その後強制的に tokio runtime に yield する。これは burst モード時 (sequencer が突然多数の block を送ってきた時) に batcher が receipt 処理で starvation するのを防ぐ細やかな最適化である。
crates/batcher/comp/src/brotli.rs (233 行) は Base 独自の brotli 圧縮ラッパーである。OP Stack のデフォルト圧縮アルゴリズムは zlib だったが、Base は brotli に変えて圧縮率を高めた—これは EIP-4844 blob の 130 KB 上限に対して非常に重要で、1% 圧縮が増えるごとに約 1% の blob 費用が減る。
3.4 シーケンサー停止履歴のコードレベル解読
2023-09-05 の Base 初メインネット停止は最終的に公式が「内部インフラのリフレッシュが必要」と帰結した (https://decrypt.co/155083/coinbase-incubated-base-suffers-outage-team-says-no-funds-are-at-risk)。事故は 43 分間続き、11,400 ブロックが出なかった (2 秒/block で推計)。
2025-08-06 の 2 度目のメインネット停止 (https://www.coindesk.com/tech/2025/08/06/base-says-sequencer-failure-caused-block-production-halt-of-33-minutes) は、Base 公式が「sequencer handoff failure」と帰結している—すなわち op-conductor が primary/standby 切り替え時にエラーを起こした。これがまさに上記の conductor モジュールが解決しようとしている問題である。
2025-10-20 (repos/base-deployments/mainnet/2025-10-20-incident-multisig-signers/) に「incident multisig signers」操作が行われた。内容は OwnerDiff.json がある multisig の署名者集合を変更するものである。これは通常「ある署名者の秘密鍵が漏洩した可能性があり、緊急ローテーションが必要」という運用操作に対応する。Base は過去 12 ヶ月の間に類似の操作を少なくとも 2 回 (2025-05-13 と 2025-10-20) 行っている。
3.5 sequencer は先回りするか? Jesse Pollak の公開姿勢
Bitcoin Ethereum News が報じた 2025-11 の Jesse Pollak 自身の creator-coin リリース時の $1.3M sniper 套利事件は、一つのことを実証している:Base sequencer 自体は先回りしないが、Flashblocks がサブブロック状態を公開した後、第三者の searcher は fee ベースの順序付けによって flashblock 境界で高度な MEV を実行できる。
具体的なメカニズム: Sniper A は flashblock N が確定したがまだブロードキャストされていない間に、メンプールを観察して同じ nonce の競争相手全員より前にランクするために自分が flashblock N+1 に入るのにどれだけの priority fee を払う必要があるかを推算する。Pollak coin のケースでは、あるウォレットが $44,000 の priority fee を支払って supply の 7.6% を獲得し、直ちに価格を吊り上げて約 $700K の利益を確定した。
Base の builder 内部コード (crates/builder/core/src/flashblocks/best_txs.rs) は厳密に priority-fee-based のソートであり—「Coinbase wallet 優先」のような特別な経路は一切ない。これは Coinbase が運営者として MEV に対して完全に commodity 立場であることを意味する:「我々は先回りしないし、ユーザーを保護もしない、priority fee が高い者が勝つ」。このスタンスは Polygon が 2025 年にローンチした private mempool ワンクリック MEV protection と対照的である。
3.6 EIP-4844 後の Base の DA コスト削減幅
arxiv 2405.03183 という IEEE 論文は EIP-4844 (2024-03-13 Dencun) 後を計測している:
- L2 データブロックサイズ 116.8% 増加
- L1 calldata 使用量 56.8% 減少
- Arbitrum/Optimism/Base/Linea の tx fee 中央値が $0.20-$1.00 から $0.01-$0.10 に低下
- Base 以降の日次活性 tx 量は 3 倍に
しかしより精確で、Base 自身が開示したコストデータは: Coinbase の 2025 通年の sequencer revenue $75.4M (全 L2 sequencer revenue の 62% を占める) (Bitget News 2025-end report)。Base の 2025 平均日次 tx 量 6-8M と組み合わせると、sequencer revenue は 1 件あたり約 $0.025-$0.034 で、これは Spotedcrypto 2026 L2 Guide で報告された tx fee 中央値 $0.01-$0.05 と整合する。
つまり、EIP-4844 は Base のユーザー向け tx fee を Dencun 前の $0.50 オーダーから $0.05 オーダーに圧縮した、削減幅 90%。これが Base が後に爆発的成長 (TVL $2.1B から $12.8B へ) できた物理的基盤である。
第四章 Smart Wallet (ERC-4337 + Passkey) の完全コードウォークスルー
4.1 ファイル構造とコード量
repos/coinbase-smart-wallet/src/:
CoinbaseSmartWallet.sol 358 行
CoinbaseSmartWalletFactory.sol 98 行
ERC1271.sol 156 行
MultiOwnable.sol 287 行
utils/ERC1271InputGenerator.sol 89 行
合計 1,000 行に満たない Solidity コードであるが、100 万人以上のユーザーに使用される (Coinbase blog 2025-08-16 参照) スマートアカウントシステムを支えている。この「コード量は極めて少ないが攻撃面は極めて大きい」という特性が監査の強度を決定する—audits/ ディレクトリには 4 件の独立した監査がある:
audits/Cantina-December-2023.pdf
audits/Cantina-April-2024.pdf
audits/Code4rena-March-2024.md
audits/Certora-February-2024.pdf
Cantina が 2 ラウンド (2023-12 初版、2024-04 修正後)、Certora が形式検証 (2024-02)、Code4rena が公開コンテスト (2024-03) を実施。これは ERC-4337 ウォレット契約の監査コストの事実上の下限であり—Coinbase はこのコードを production に押し上げるのに推定 $500K-$1M を費やしている。
4.2 REPLAYABLE_NONCE_KEY = 8453 の位置と意味
repos/coinbase-smart-wallet/src/CoinbaseSmartWallet.sol の 51 行目:
uint256 public constant REPLAYABLE_NONCE_KEY = 8453;
8453 は Base mainnet の Chain ID である。この数字は定数として wallet コントラクトにハードコードされ、UserOperation.nonce の上位 192 bit のキーとして「これはクロスチェーンでリプレイ可能な user operation である」ことを識別する。
161-188 行目の validateUserOp 関数がこのすべての中核である:
function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
external
virtual
onlyEntryPoint
payPrefund(missingAccountFunds)
returns (uint256 validationData)
{
uint256 key = userOp.nonce >> 64;
if (bytes4(userOp.callData) == this.executeWithoutChainIdValidation.selector) {
userOpHash = getUserOpHashWithoutChainId(userOp);
if (key != REPLAYABLE_NONCE_KEY) {
revert InvalidNonceKey(key);
}
// Check for upgrade calls in the batch and validate implementation has code
bytes[] memory calls = abi.decode(userOp.callData[4:], (bytes[]));
for (uint256 i; i < calls.length; i++) {
bytes memory callData = calls[i];
bytes4 selector = bytes4(callData);
if (selector == UUPSUpgradeable.upgradeToAndCall.selector) {
address newImplementation;
assembly {
newImplementation := mload(add(callData, 36))
}
if (newImplementation.code.length == 0) revert InvalidImplementation(newImplementation);
}
}
} else {
if (key == REPLAYABLE_NONCE_KEY) {
revert InvalidNonceKey(key);
}
}
...
}
全体のロジックは以下のように要約できる:
- nonce の上位 192 bit を
keyとして取得 - もし calldata が
executeWithoutChainIdValidation(特殊な関数、セレクタ =0xbf6ba1fc) を呼び出す場合:
- 必ず REPLAYABLE_NONCE_KEY (8453) をキーとして使用しなければならない
- userOpHash を再計算する際にchain ID を剥がす (つまり同じ hash が全チェーンで有効)
- もしアップグレード呼び出しなら、implementation アドレスにコードがあるかを確認 - それ以外:
- REPLAYABLE_NONCE_KEY の使用を禁止
なぜか? クロスチェーンリプレイは「sign once, update everywhere」のためである—ユーザーは Base mainnet で「新しい owner を追加」あるいは「implementation をアップグレード」に一度署名すれば、同じ user operation を Optimism、Polygon、Arbitrum など同じ wallet contract をデプロイした全チェーンでリプレイできる。しかしクロスチェーンリプレイの前提はchain ID と無関係であることで、だからこそ予約された nonce key で区別しなければならない。
この数字に 8453 を選んだことには非常に皮肉な意味的二重性がある:Coinbase は Base の chain ID を「全チェーン共通」キーとして用いている—「母艦」のような姿勢、ただし契約セマンティクス上 8453 は Base mainnet 自体と特別な関係を持たない (理論的には 1234 でも構わない)。
4.3 MultiOwnable: EOA と passkey を同時サポート
repos/coinbase-smart-wallet/src/MultiOwnable.sol (287 行) は、Ethereum アドレス (20 バイト) と secp256r1 public key (64 バイト) の両方を owner として同時にサポートするマルチシグメカニズムを実装している。ストレージレイアウトを単純化すると:
mapping(uint256 index => bytes owner) ownerAtIndex;
mapping(bytes owner => bool isOwner) isOwner;
uint256 nextOwnerIndex;
owner は address ではなく bytes 型でストレージされる—2 種類の長さを同時に収容するためである。CoinbaseSmartWallet の SignatureWrapper (25-31 行目):
struct SignatureWrapper {
/// @dev The index of the owner that signed, see `MultiOwnable.ownerAtIndex`
uint256 ownerIndex;
/// @dev If `MultiOwnable.ownerAtIndex` is an Ethereum address, this should be `abi.encodePacked(r, s, v)`
/// If `MultiOwnable.ownerAtIndex` is a public key, this should be `abi.encode(WebAuthnAuth)`.
bytes signatureData;
}
ownerIndex フィールドは必須である。secp256r1 検証は事前に公開鍵を知っている必要があるためだ (ECDSA の ecrecover が署名から逆算して address を導けるのとは異なる)。設計上、公開鍵そのものではなく index を渡すのは calldata を節約するためである—calldata は L2 における主要コストだ。
4.4 WebAuthn 検証: base-webauthn リポジトリ
repos/base-webauthn/src/WebAuthn.sol は Coinbase が Daimo の webauthn 検証ライブラリ を fork して最適化したバージョンである。コアデータ構造 (README.md から引用):
struct WebAuthnAuth {
bytes authenticatorData;
string clientDataJSON;
uint256 challengeIndex;
uint256 typeIndex;
uint256 r;
uint256 s;
}
function verify(
bytes memory challenge,
bool requireUserVerification,
WebAuthnAuth memory webAuthnAuth,
uint256 x,
uint256 y
) internal view returns (bool)
性能最適化の鍵は RIP-7212 precompile の使用である。RIP-7212 は EVM に secp256r1 検証 precompile (アドレス 0x100) を追加する。OP Stack チェーン (Base 含む) では RIP-7212 が既に有効化されているため、WebAuthn.verify は precompile 経由でわずか ~3,450 gas で済む。RIP-7212 がないチェーンでは FreshCryptoLib 実装にフォールバックして ~330,000 gas を要する—約 100 倍の差。
ただし README は警告もしている:
FreshCryptoLib uses the
ModExpprecompile (address(0x05)), which is not supported on some chains, such as Polygon zkEVM. This library will not work on such chains, unless they support the RIP-7212 precompile.
これは Base smart wallet がクロスチェーンデプロイされる際の隠れた制約である: ModExp または RIP-7212 をサポートするチェーンにデプロイされなければならず、Polygon zkEVM では実質的に動かない。
4.5 Permissions システム (Session Keys)
repos/coinbase-smart-wallet-permissions/src/SpendPermissionManager.sol は独立したコントラクト (365 行) であり、周期的な消費限度 (recurring spend allowance) を実装している:
struct SpendPermission {
address account; // スマートアカウント
address spender; // 支出を許可される主体
address token; // ERC-7528 ether または ERC-20
uint48 start; // 有効開始時刻
uint48 end; // 失効時刻
uint48 period; // 周期 (秒)
uint160 allowance; // 周期あたり最大消費
}
struct PeriodSpend {
uint48 start;
uint48 end;
uint160 spend;
}
これは本質的に Web3 版「クレジットカード限度」である—ユーザーは spender (例えばあるDEX の router) に対して、日次/月次で特定の token を最大いくらまで使うことを許可する。許可は EIP-712 typed-data 署名で行い、オンチェーンでは _isApproved mapping に保存される。spend の累計は _lastUpdatedPeriod に保存され、周期が終わると自動的にゼロにリセットされる。
これが Coinbase smart wallet の核となる UX のブレークスルーである:ユーザーはアプリに対して高頻度トランザクションを各回確認なしで許可できる。これがまさに Bitcoin.com の報道 で「smart wallet driving Base app innovation」と語られていることのコントラクトレベルの基盤である。
このリポジトリの README.md の 18-19 行目には非常に率直な免責事項がある:
Note: These contracts are currently unaudited and are only recommended for testing purposes. Use at your own risk.
つまり、Permissions システムは現時点 (2026-04 にクローンした時点) でまだ正式な監査が完了していないが、既にメインネットにデプロイされ、本番アプリで使用されている。これは Base がマークするに値するセキュリティリスクである。
4.6 Paymaster: base-paymaster リポジトリ
repos/base-paymaster/ は ERC-4337 VerifyingPaymaster の fork である。README.md の 4-7 行目:
This repo contains a verifying paymaster contract that can be used for gas subsidies for ERC-4337 transactions.
It contains a clone of the eth-infinitism VerifyingPaymaster with an additionalreceivefunction for simple deposits, as well as some additional changes made in response to an audit.
ワークフローは 2 つの JSON-RPC メソッドを通じて開発者に公開される:
eth_paymasterAndDataForEstimateGas: gas 推定用の dummy signature を取得eth_paymasterAndDataForUserOperation: 真の paymaster signature を取得
paymaster.base.org は Coinbase が運営する中央集権的な paymaster サービスで、CDP (Coinbase Developer Platform) ダッシュボードで開発者に sponsorship 限度を設定させる。Coinbase は各プロジェクトに 最大 $15K の gas クレジット を提供する (CDP Paymaster Masterclass)。
デプロイアドレス (Base Sepolia 上の verifying paymaster):
0xf5d253B62543C6Ef526309D497f619CeF95aD430
Mainnet paymaster アドレスは paymaster.base.org API 経由で動的に返され、ハードコードされたコントラクトではない。この点は BasePaymaster の設計哲学と一致する—paymaster は静的コントラクトではなく動的サービスである。
4.7 Cantina と Code4rena の監査所見
Cantina 2024-04 (audits/Cantina-April-2024.pdf) で報告された最も重要な発見 (Cantina portfolio より引用):
Users are able to upgrade their account’s owners via either directly onto the contract with a regular transaction or via an ERC-4337 EntryPoint transaction calling executeWithoutChainIdValidation. If a user chooses to use a combination of these methods it’s very likely that the addresses at a particular ownership index differ across chain. Therefore if a user later calls removeOwnerAtIndex on another chain will end up removing different addresses on different chains. The severity of this ranges from minimal (the user can just add the mistakenly removed owner back) or critical (the user mistakenly removes their only accessible owner on a specific chain, permanently locking the account).
これはクロスチェーンリプレイ可能トランザクション設計がもたらす構造的リスクである: 同じ wallet が異なるチェーン上で owner index が desync する可能性がある。Coinbase の mitigation は、フロントエンド UI でユーザーに常に executeWithoutChainIdValidation を経由して owner を変更するよう強制プロンプトを表示することだが、契約層では強制できない。
Code4rena 2024-03 contest (audits/Code4rena-March-2024.md、公開 code4rena.com/reports/2024-03-coinbase) では複数の medium 級 issue が見つかったが、critical はなかった。これはコントラクトそのものは極小だが繰り返し監査されており、production デプロイ前にさらに内部 review があった可能性を示唆する。
第五章 Basenames (base.eth ドメインネームシステム) の完全分析
5.1 ENS との関係
repos/base-basenames/README.md の 5-7 行目に明確に書かれている:
This repository contains code for minting and managing ENS subdomains on the Base network as
base.ethsubdomains.
つまり Basenames は全く新しい命名システムではなく、ENS の「拡張」である—base.eth は Ethereum mainnet 上での ENS の 2LD (second-level domain) で、Coinbase がこのドメイン名を所有し、CCIP-Read (ENSIP-10) を通じて全ての *.base.eth サブドメイン解決を Base L2 に委任している。
コード構造は ENS コントラクトの “slimmed down fork” である:
| ENS コントラクト | Basenames 等価物 | 主な相違 |
|---|---|---|
ENSRegistry.sol |
Registry.sol |
ほぼ同一 |
BaseRegistrarImplementation.sol |
BaseRegistrar.sol |
同一 |
ReverseRegistrar.sol |
ReverseRegistrar.sol |
同一 |
OffchainResolver.sol (CCIP-Read) |
L1Resolver.sol |
L1 側 |
PublicResolver.sol |
L2Resolver.sol |
L2 側 |
ETHRegistrarController.sol |
RegistrarController.sol |
discount validator 追加 |
StablePriceOracle.sol |
StablePriceOracle.sol |
同一 |
ExponentialPremiumPriceOracle.sol |
ExponentialPremiumPricingOracle.sol |
同一 |
5.2 メインネットデプロイアドレス (README からの転記、BaseScan で検証可能)
Ethereum L1:
- L1Resolver: 0xde9049636F4a1dfE0a64d1bFe3155C0A14C54F31
Base Mainnet:
- Registry: 0xb94704422c2a1e396835a571837aa5ae53285a95
- BaseRegistrar: 0x03c4738ee98ae44591e1a4a4f3cab6641d95dd9a
- RegistrarController: 0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5
- Launch Price Oracle: 0xd53b558e1f07289acedf028d226974abba258312
- Price Oracle: 0x508CFE43aa84b8048cB6d39037cE0dc96d8aDc75
- ReverseRegistrar: 0x79ea96012eea67a83431f1701b3dff7e37f9e282
- L2Resolver: 0xC6d566A56A1aFf6508b41f6c90ff131615583BCD
- UpgradeableRegistrarController (Proxy): 0xa7d2607c6BD39Ae9521e514026CBB078405Ab322
- UpgradeableL2Resolver (Proxy): 0x426fA03fB86E510d0Dd9F70335Cf102a98b10875
- ProxyAdmin: 0x6c8E23DaCCc002d2Bca7608EC0351E434E74d5a8
5.3 経済モデルと discount validator
Basenames の登録費は ENS と類似しており、name length × duration で課金されるが、Coinbase は専用の割引検証器メカニズムを追加している。RegistrarController は validationData パラメータを受け付け、IDiscountValidator インターフェースを実装するコントラクトは独自のロジックで特定の登録が割引を享受するかを決定できる。
公開された discount validator には:
- Coinbase ユーザー本人認証 (Coinbase アカウント保有者は 6 文字以上の name を無料に)
- Coinbase Verified Account NFT 検証
- 早期登録者報酬
- パートナープロモーション
これらの validator 自体は独立してデプロイされた小さなコントラクトであり、ProxyAdmin で管理される。この「プラグイン化割引」が Basenames が ENS よりも商業化されている部分である—ENS は完全にコモディティ、Basenames は Coinbase のユーザー成長ツールである。
5.4 登録数と分配
repos/base-deployments/mainnet/2024-08-27-disburse-basenames/disbursement.json (76 行) は Base チームが 2024-08-27 に行った「バルク分配」操作の記録で、複数の Basenames をコミュニティメンバー/Coinbase ユーザー/早期サポーターに直接配布したものである。この種の disbursement は ENS の初期にも行われていた (Twitter ENS 早期サポーターへの無料 .eth 配布)。
Coinbase は Basenames の総登録数を公開していないが、Bitget News のレポート によれば、Base の 2025 通年の “identity-related revenue” (主に Basenames + smart wallet) は sequencer revenue の約 8-12% を占め、絶対値で $5-10M オーダーである。
5.5 CCIP-Read 解決 (ENSIP-10)
L1 上の L1Resolver は CCIP-Read プロトコル (EIP-3668) を実装する。L1 上のアプリが vitalik.base.eth を問い合わせると:
- アプリが L1Resolver.resolve(name, data) を呼ぶ
- L1Resolver が
OffchainLookup(sender, urls, callData, callbackFunction, extraData)で revert - アプリ (あるいは ethers/viem) が自動的に urls に従って CCIP gateway に問い合わせる
- gateway が Base L2 から実データ + signature を取得して返す
- アプリが L1Resolver.callback を呼んで signature を検証し、データを返す
L1Resolver アドレス 0xde9049… は 2024-07-23 に置き換えられ (repos/base-deployments/mainnet/2024-07-23-set-l1-resolver/)、2024-07-30 に再び置き換えられた (2024-07-30-set-new-l1-resolver/)。この 2 回の置換はおそらく CCIP gateway 側の修正または拡張である。
第六章 op-enclave (TEE) ルート
6.1 base/base 内部 TEE との関係
repos/base-op-enclave は Base が 2023-2025 期に独立してメンテナンスしていた Go リポジトリであり、現在の base/base monorepo 内の crates/proof/tee/ とは同じ思想の 2 世代の実装である:
- op-enclave (Go, 2023-2025): 単一の OP Stack chain (主に Base appchains) に対して完全な batcher + proposer + enclave + withdrawer を一括提供する fork
- base-base/crates/proof/tee (Rust, 2026-): 独立クレートに分割され、base/base メインリポジトリに統合、Base mainnet 自体にサービス
op-enclave リポジトリの README.md (op-enclave サブディレクトリ):
op-enclave: Stateless transition function, for running in an AWS Nitro TEE
op-proposer: L2-Output Submitter, communicates with op-enclave and submits proposals to L1
op-withdrawer: Withdrawal utility for submitting withdrawals to L1
6.2 op-enclave の「即時出金」メカニズム
repos/base-op-enclave/README.md の 6-9 行目で、この selling point が前面に出されている:
This removes the need for the 7-day challenge period, and allows for immediate withdrawals.
具体的にどう実装するか?
- batcher 変種: ある block に withdrawal event が含まれていれば、batcher は直ちに channel を close して提出する、蓄積を待たない。これが base appchains blog で言われている “The batcher is modified such that if a block contains a withdrawal event, the batcher immediately treats the current channel as full and submits the batch to L2.” である。
- proposer 変種: proposer が enclave と通信し、enclave は「この L2 block までの状態は合法である」という署名付き attestation を出す。proposer はこの attestation を L1 に提出する。
- L1 検証コントラクト: attestation 内の PCR0 が allowlist にあること、signer が allowlist にあること、X.509 証明書チェーンが合法であることを検証。
全プロセスで 7 日 challenge period は不要である。L1 コントラクトが attestation を信用するからだ。出金 latency は実際には「batcher 提出を待つ + enclave が attestation に署名するのを待つ + L1 12 秒/slot を待つ」となり、約 5-10 分。
6.3 「従来の不正証明」との対比
| OP Stack デフォルト fault proof | op-enclave (TEE) | OP Succinct (ZK) | Base Azul (TEE + ZK) | |
|---|---|---|---|---|
| 信用前提 | 1-of-N challenger が誠実 | TEE ハードウェア + AWS attestation が誠実 | 数学/暗号学 | TEE + ZK の両方が破られない |
| 出金遅延 | 7 日 | 5-10 分 | 30-60 分 | 5-10 分 (TEE) または 30 分 (ZK) |
| proof あたりコスト | $0 (チャレンジ次第) | ~$0.01 (TEE attestation) | $1-2 (SP1) | TEE + ZK 二重コスト |
| アップグレード周期 | 月 | 数時間 (enclave image 置換) | 週-月 | 複雑 |
| オンチェーン attack surface | 大 (MIPS VM) | 中 (X.509 + Nitro verifier) | 小 (SP1 verifier) | 大 (TEE + ZK 双方が露出) |
Base は単一の方式を選ぶのではなく、TEE + ZK + 従来の challenger を同時にデプロイしている。この「ベルトとサスペンダー」戦略は、$12B を預かるチェーンには合理的である—ただしコストは開発と運用の複雑度が単一チェーンより一桁多くなることだ。
6.4 op-enclave の PCR0 + signer 二重 allowlist
具体的に L1 コントラクトでは、op-enclave は SystemConfigGlobal (op-enclave が導入した新しいコントラクト) を通じて 2 つの allowlist を維持する:
- PCR0 allowlist: どの enclave image hash が許可されているか (通常 1-3 バージョンが同時に有効、グレーリリース対応のため)
- signer allowlist: どの ECDSA アドレス (enclave 内部で生成された秘密鍵に対応するアドレス) が許可されているか
いかなる attestation も PCR0 ∈ allowlist かつ signer ∈ allowlist でなければ受理されない。repos/base-op-enclave/tools/ はコマンドラインツール register-keys と verify-pcr0 を提供する。
この「二層 allowlist」は単一障害点を防ぐためである:
- もし PCR0 が悪意ある enclave image に注入されたら → signer は変わらないが、allowlist の更新が必要
- もし signer 秘密鍵が漏洩したら (理論的には enclave 内部 RNG にバグがなければ起こらない) → 即座に allowlist から削除、新たな attestation 署名は無効
6.5 base/base リポジトリ内の nitro-attestation-prover
crates/proof/tee/nitro-attestation-prover/ は Base が Nitro attestation を ZK proof に変換するブリッジである。サブモジュール (コードから):
src/lib.rs - module entry
src/types.rs - AttestationProof などの型
src/error.rs - error types
src/direct.rs - NSM 経由 (enclave 内) で署名する直接経路
src/boundless.rs - Boundless ネットワーク経由で attestation の ZK proof を生成 (~1,027 行)
boundless.rs が最も複雑—Nitro attestation document を Boundless ネットワーク に渡して、「この attestation document を合法的にパースし、その中の PCR0 = X、signer = Y である」ことを証明する RISC0 zkVM の証明を生成する。そしてこの ZK proof は L1 に TEE prover が TEEProverRegistry に登録される際の認証情報として提出される。
このメカニズムの目的は:AWS の X.509 証明書チェーン検証を L1 EVM コントラクトから除去すること—EVM で直接 X.509 証明書チェーンを検証する gas コストは極めて高い (1 回約 500K-1M gas)。ZK proof によって X.509 検証は zkVM 外で完了し、L1 上では 1 つの ZK proof を検証するだけ (~$1-2 gas)。
第七章 AgentKit と OnchainKit
7.1 AgentKit: AI agent + wallet の標準化ラップ
repos/coinbase-agentkit/ は Coinbase Developer Platform が 2024 後期にリリースした、AI agent 専用の wallet ツールキットである。リポジトリ構造:
python/ - Python SDK
typescript/ - TypeScript SDK
README.md の tagline:
AgentKit
Every agent deserves a wallet.
コアポジショニング:
AgentKit is Coinbase Developer Platform’s toolkit for giving AI agents a crypto wallet and onchain interactions. It is designed to be framework-agnostic, so you can use it with any AI framework, and wallet-agnostic, so you can use it with any wallet.
サポートする AI フレームワークには LangChain、CrewAI、Eliza、Vercel AI SDK などが含まれる; サポートする wallet には Coinbase Smart Wallet、Privy、Dynamic、MetaMask などが含まれる。
AgentKit の action 体系
AgentKit の中核 abstraction は Action である—1 つのアトミックなオンチェーン操作で、以下を含む:
class Action:
name: str # 一意識別子
description: str # LLM 向け prompt
schema: pydantic.BaseModel # パラメータ型
invoke: Callable # 実際の実行
LLM は function calling / tool use を通じて action を呼び出す。各 action の Base 上のトランザクションは paymaster によって自動 sponsor される (gas-free)。
Base 戦略との協同
AgentKit は Base 専用ではない—Base + Polygon + Optimism + Arbitrum + Ethereum mainnet をサポートする—ただしデフォルトチェーンは Base であり、独自の “fee-free stablecoin payments” を提供する。これは Coinbase が AI agent 市場を Base に誘導するコアな vehicle である。
7.2 OnchainKit: React コンポーネントライブラリ + utility
repos/coinbase-onchainkit/ はフロントエンド開発者向けの React コンポーネントライブラリである。構造:
packages/
├── onchainkit/ # メインパッケージ
├── create-onchain/ # CLI スキャフォールド
├── miniapp-manifest-generator/ # MiniApp manifest 生成
├── playground/ # 内部テスト場
メインパッケージ @coinbase/onchainkit は npm 上で顕著なダウンロード量がある (README に npm バッジが引用されているが、具体的な数字は非公開)。コンポーネントは以下を含む:
<Identity />- ENS/Basenames + avatar + verifications を表示<Wallet />- ワンクリックで Coinbase Smart Wallet に接続<Transaction />- ラップ済みの ERC-4337 user operation 提出<Swap />- Aerodrome/Uniswap 統合<NFT />/<Frame />- Farcaster Frames 統合<Earn />- Morpho yield 統合
OnchainKit の中核戦略は、「Base 上で何かを行う際の UX の痛点」をすべて数行の JSX にラップし、フロントエンド開発の障壁を下げることである。これが Base の開発者吸引力におけるソフトウェアの濠である—競合 (Arbitrum、Optimism) には同等の公式コンポーネントライブラリがない。
7.3 AgentKit + OnchainKit の 2025-2026 における市場意義
Coinbase developer blog が 2025-08 に発表した “Base App” のリブランディングは、OnchainKit を first-class ツールの地位に押し上げた—Base App のフロントエンド全体が OnchainKit で構築されており、Base App でリリースされるすべての mini-app は自動的に OnchainKit のスタイルを継承する。これは Coinbase が Base を「インフラ」から「コンシューマプロダクト」へとパッケージングする鍵となる一歩である。
AgentKit の隆盛は 2025-2026 の AI agent エコノミー叙述と完全に同期している。AI agent には KYC が不要、パスワードも不要、必要なのは wallet である。AgentKit によって Coinbase がこの市場のデフォルト onramp となった。
第八章 Bridge コントラクトの深掘り
8.1 L1 コアコントラクトアドレス (base-deployments/mainnet/addresses.json から)
repos/base-deployments/mainnet/addresses.json:
{
"AddressManager": "0x8EfB6B5c4767B09Dc9AA6Af4eAA89F749522BaE2",
"L1CrossDomainMessengerProxy": "0x866E82a600A1414e583f7F13623F1aC5d58b0Afa",
"L1ERC721BridgeProxy": "0x608d94945A64503E642E6370Ec598e519a2C1E53",
"L1StandardBridgeProxy": "0x3154Cf16ccdb4C6d922629664174b904d80F2C35",
"L2OutputOracleProxy": "0x56315b90c40730925ec5485cf004d835058518A0",
"OptimismMintableERC20FactoryProxy": "0x05cc379EBD9B30BbA19C6fA282AB29218EC61D84",
"OptimismPortalProxy": "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e",
"ProxyAdmin": "0x0475cBCAebd9CE8AfA5025828d5b98DFb67E059E",
"SystemConfigProxy": "0x73a79Fab69143498Ed3712e519A88a918e1f4072",
"SystemDictatorProxy": "0x1fE3fdd1F0193Dd657C0a9AAC37314D6B479E557"
}
すべてのコントラクトは etherscan で検証可能:
- L1StandardBridge: 0x3154Cf16ccdb4C6d922629664174b904d80F2C35 — ETH と ERC-20 標準ブリッジ
- OptimismPortal: 0x49048044D57e1C92A77f79988d21Fa8fAF74E97e — ユーザー預入口、出金検証
- L2OutputOracle: 0x56315b90c40730925ec5485cf004d835058518A0 — 旧版 output 提出 (2024-10-30 fault proof アップグレード後は停止しているが、コントラクトは存在)
- SystemConfig: 0x73a79Fab69143498Ed3712e519A88a918e1f4072 — gas 設定 + batcher inbox アドレス + L2 chain ID
- ProxyAdmin: 0x0475cBCAebd9CE8AfA5025828d5b98DFb67E059E — すべての proxy のアップグレード権限保持者
8.2 ProxyAdmin owner: Base Governance Multisig
L2BEAT Base page と Base 公式 blog によれば:
All contracts are upgradable by a ProxyAdmin contract controlled by a nested 2/2 Base Governance Multisig composed of the Base Coordinator Multisig and the Base Security Council.
具体的には 2-of-2 nested multisig である:
- Base Coordinator Multisig (Coinbase / Base チームが管理)
- Base Security Council (独立メンバーで構成)
両方の署名がなければアップグレードを発動できない。Base は 2025-01-15 (2025-01-15-nested-ownership-transfer/signers.json) にこの ownership transfer を完了し、ProxyAdmin を初期の単純な 2/2 multisig から nested 2/2 + Security Council 構造に変更した。
Challenger ロールは独立した 1-of-2 である: Base チームまたは Optimism Foundation のどちらかが単独で challenge を提出して invalid output 提案を削除できる。この「どちらでも挑戦可能」は片方の機能不全を防ぐためである。
8.3 アップグレード履歴の完全タイムライン
repos/base-deployments/mainnet/ 配下には 99 個のタイムスタンプディレクトリがあり、それぞれが実際のオンチェーン操作に対応する。時系列で簡単に:
2023-Q3 メインネットローンチ期:
- 2023-06-14 deploy: 初期デプロイ
- 2023-06-15 unpause-portal: OptimismPortal のアンロック
- 2023-06-15 validate-deploy: デプロイ検証
- 2023-06-21 transfer-system-cfg-owner: SystemConfig 所有権移転
- 2023-07-19 challenger-1-of-2: 1-of-2 challenger 構造を設定 (Base メインネットローンチから約 1 ヶ月後)
- 2023-07-26 transfer-owner-nested-safes: nested safe への移転
2024 Ecotone & Holocene 期:
- 2024-03-07 ecotone-sysconfig-updates: Ecotone 設定更新
- 2024-04-12 deployERC20Factory: ERC-20 ファクトリーデプロイ
- 2024-08-27 disburse-basenames: Basenames バルク分配
- 2024-12-18 holocene-deployments: Holocene ハードフォークデプロイ
2025 fault proofs の複数回反復:
- 2025-01-15 nested-ownership-transfer: nested multisig へ移行
- 2025-03-05 upgrade-fault-proofs: faultDisputeGame + permissionedDisputeGame アップグレード
- 2025-04-23 upgrade-fault-proofs (Upgrade 15 / Isthmus): Isthmus ハードフォークと同時に fault proof アップグレード
- 2025-05-13 incident-multisig-signers: 緊急 multisig 署名者ローテーション
- 2025-06-04 upgrade-system-config: SystemConfig アップグレード
- 2025-08-13 safe-swap-owner: Safe owner ローテーション
- 2025-10-20 incident-multisig-signers: 再度の緊急ローテーション
- 2025-11-21 u17-jovian-upgrade (Upgrade 17 / Jovian): Jovian ハードフォーク + fault proof VM メンテナンス
- 2025-11-25 base-bridge-deployment: 新しいブリッジのデプロイ (おそらく Azul の準備)
- 2025-12-01 pause-bridge-base: あるブリッジを一時停止
- 2025-12-04 set-jovian-parameters: Jovian パラメータ設定
2026 Azul 準備期:
- 2026-01-09 op-stack-upgrade-18 (Upgrade 18): OP Contracts Manager アップグレード
- 2026-02-19 superchain-separation: Base が Superchain から分離 (これは Base が Azul 自治 ZK ルートを準備する鍵となる一歩)
- 2026-02-27 pause-superchain-config: Superchain config を一時停止
- 2026-03-11 patch-fee-disburser: fee disburser パッチ
- 2026-03-25 increase-gas-and-elasticity-limit: gas 上限と弾性を増加
各操作には README.md があり、motivation、procedure、signature collection プロセス、verifying-tx リンクが明記されている。これらのディレクトリを合わせると、Base メインネットの完全な「憲法進化史」を形成する。
8.4 USDC ネイティブ統合: CCTP
Circle は 2023-09 にネイティブ USDC を Base に接続した、Cross-Chain Transfer Protocol (CCTP) を通じて。CCTP は OP Stack 標準ブリッジ (L1StandardBridge) を通らず、burn-and-mint モデルを採る:
- ユーザーが Ethereum mainnet 上で Circle の
TokenMessengerコントラクトのdepositForBurn(amount, destinationDomain=6, mintRecipient, USDC)を呼ぶ - Ethereum 上の USDC が burn され、
MessageSentevent が emit される - Circle の attestation service (オフチェーン) が event を見て attestation を発行
- ユーザー (または relayer) が Base 上で
MessageTransmitterを呼んで attestation でMessageReceivedをトリガー - Base 上で USDC が mint される
プロセス全体が Base の OP Stack ブリッジに依存しないため、challenge period は不要だが、Circle の attestation service に依存する—これは完全に中央集権的な信頼の根である。CCTP v2 (2025) は Fast Transfer (Circle が流動性を事前 mint) と Hooks (クロスチェーンコントラクト関数呼び出し) を追加し、latency を秒単位まで圧縮した。
Coinbase は Base 上で native USDC (USDbC = bridged USDC ではなく) を推進する傾向にある、native USDC の方が流動性が深く、OP Stack ブリッジの 7 日 challenge と結びつかないからである。
8.5 OptimismPortal v2 と fault proof 後の出金経路
2024-10-30 の fault proof リリース後、出金経路に根本的な変化が起きた:
旧経路 (2024-10-30 以前):
1. ユーザーが Base 上で L2ToL1MessagePasser.initiateWithdrawal を呼ぶ
2. sequencer が L1 上で L2OutputOracle.proposeL2Output を通じて対応する output root を提出するのを待つ
3. ユーザーが L1 上で OptimismPortal.proveWithdrawalTransaction(_tx, _l2OutputIndex, _outputRootProof, _withdrawalProof) を呼ぶ
4. 7 日 challenge period を待つ
5. OptimismPortal.finalizeWithdrawalTransaction を呼ぶ
新経路 (2024-10-30 以後、Base Azul 以前):
1. ユーザーが Base 上で L2ToL1MessagePasser.initiateWithdrawal を呼ぶ
2. proposer が DisputeGameFactory.create(GAME_TYPE_CANNON, rootClaim, extraData) を通じて game を作成するのを待つ
3. game が IN_PROGRESS に入るのを待つ、その間 challenger が dispute できる
4. game が DEFENDER_WINS した後、RESPECTED_GAME_TYPE 内の game output root が OptimismPortal に受理される
5. ユーザーが OptimismPortal.proveWithdrawalTransaction(_tx, _disputeGameProxy, _outputRootProof, _withdrawalProof) を呼ぶ
6. airgap (通常 3.5-7 日) と game finalized を待つ
7. OptimismPortal.finalizeWithdrawalTransaction を呼ぶ
Azul 以後 (2026-05):
1. ユーザーが Base 上で L2ToL1MessagePasser.initiateWithdrawal を呼ぶ
2. proposer が TEE と ZK の両方の proof を含む game を提出
3. game が短時間で finalized (TEE 経路 < 30 分、ZK 経路 < 1 時間)
4. ユーザーが proveWithdrawalTransaction を呼ぶ
5. 短い airgap (< 1 日)
6. finalizeWithdrawalTransaction を呼ぶ
これが Yellow.com の報道 で Base Azul が “replacing the multi-day challenge period of an optimistic rollup with cryptographic finality” と呼ばれている理由である。
第九章 性能データと既知の脆弱性
9.1 実 TPS、Block Time、Finality
Base の 2026-05 における実運用パラメータ:
- Block time: 2 秒 (
repos/base-base/crates/builder/core/src/config.rs:175の production デフォルトblock_time: Duration::from_secs(2)にハードコード、テスト用は 1 秒) - Flashblocks interval: 200ms (
crates/builder/core/src/config.rs:174) - 各 block は 10 個の flashblock を含む (2s / 200ms)
- 理論 TPS 上限: gas limit 200M / 平均 simple-transfer 21K gas = ~9,500 tx/2s = ~4,750 TPS
- 実際の平均 TPS (Bitget News 2025 report から推計): ~100-200 TPS、ピーク約 800 TPS
- L1 finality: 12 分 (Ethereum 2 epoch)
- Base 自身の L2 finality (Azul 以後): ZK proof 提出後約 1-2 時間
- TVL (2026-04): $10.7-12.8B、L2 でランキング 2 位
9.2 EIP-4844 後の実 gas コスト
| チェーン | 平均 swap 費用 | 平均 simple transfer 費用 |
|---|---|---|
| Base | $0.02-0.10 | $0.005-0.02 |
| Arbitrum | $0.05-0.20 | $0.01-0.05 |
| Optimism | $0.05-0.20 | $0.01-0.04 |
| Polygon | $0.001-0.01 | $0.0005-0.005 |
| Ethereum L1 | $5-50 | $1-10 |
Base が Arbitrum/Optimism よりわずかに安いのは、主に以下の理由による:
1. brotli 圧縮が zlib より 10-15% 高い
2. Base は自社で sequencer を運営し、priority fee 収益を base fee 引き下げに再投資
3. Flashblocks により builder が 200ms 以内により最適な tx 選択を行え、wasted block space を減らす
9.3 既知の脆弱性と bug bounty
Coinbase Smart Wallet:
- Cantina 2024-04 が cross-chain owner index desync issue を発見 (severity: 最悪ケースで critical)、フロントエンド UI mitigation で対応
- Code4rena 2024-03: 複数の medium severity、修正済み
- Cantina 2024-04: 完全に監査済み
Coinbase Smart Wallet Permissions:
- 2026-04 時点でも 未監査 状態 (README の 18 行目より)
- これはマークすべきセキュリティリスク—既にメインネットにデプロイされ、本番アプリで使用されている
Base L1 コントラクト:
- OpenZeppelin の OP Stack 標準監査
- Sigma Prime の op-batcher 監査 (Optimism が委託、Base が間接的に恩恵)
- Trail of Bits の OptimismPortal 監査
- Spearbit の複数の fault proof アップグレード監査
Immunefi bug bounty:
- Base は Optimism の bug bounty を流用 (https://immunefi.com/bug-bounty/optimism/)
- 最高 critical 報酬 $2M
- Base は別途 https://hackerone.com/coinbase 汎用 bounty を維持、smart wallet も含む
既知の歴史的脆弱性 (公開開示):
- OptimismPortal2 withdrawal invalidation bug (2024-09, Optimism docs issue #12175): dispute game システム内で、特定の境界条件下で withdrawal が invalidated される可能性。パッチで修正済み、Base メインネットは当時緊急アップグレードで追随。
- WebAuthn-sol の初期バージョンが user verification flag のチェックをサポートしておらず、Cantina の報告後に修正
9.4 セキュリティ監査報告リスト (時系列)
| 時期 | 監査者 | 範囲 | 報告位置 |
|---|---|---|---|
| 2023-12 | Cantina | Coinbase Smart Wallet 初版 | repos/coinbase-smart-wallet/audits/Cantina-December-2023.pdf |
| 2024-02 | Certora | Coinbase Smart Wallet 形式検証 | repos/coinbase-smart-wallet/audits/Certora-February-2024.pdf |
| 2024-03 | Code4rena | Coinbase Smart Wallet 公開コンテスト | repos/coinbase-smart-wallet/audits/Code4rena-March-2024.md |
| 2024-04 | Cantina | Coinbase Smart Wallet 修正後 | repos/coinbase-smart-wallet/audits/Cantina-April-2024.pdf |
| ? | ? | Basenames | repos/base-basenames/audit/ (監査者は明記されていない) |
| ? | ? | WebAuthn-sol | repos/base-webauthn/audits/ |
| ? | ? | base-paymaster | repos/base-paymaster/audits/ |
各リポジトリの audits/ ディレクトリには少なくとも 1 件の PDF が含まれているが、具体的な監査者は完全に公開されていない場合がある。
第十章 総合判断と未解決の問題
10.1 Base 技術内核の 5 つの重要な判断
-
Rust 書き換えはマーケティングのスタントではなくインフラ戦略である: base/base monorepo は Base クライアント全体を Go/Optimism エコシステムから Rust/Paradigm エコシステムに切り替えた。これにより Base チームには (a) reth ExEx への直接制御権、(b) zkVM フレンドリーな STF への進路、(c) Go 版クライアントより 3-5 倍高い throughput の余地が与えられた。
-
Flashblocks は UX のブレークスルーであり MEV vector でもある: 200ms preconfirmation でユーザー体験が秒級になるが、同時に sniper に新たなメンプール観察ウィンドウを与えてしまう。Pollak coin 事件は、Base が builder 層で「中立的な priority-fee ordering」を選択し、MEV ガバナンスをアプリ層に外部委託していることを実証している。
-
3 トラックフォールトプルーフは over-engineered だが、$12B 資産チェーンには合理的: TEE + ZK + traditional challenger が同時に稼働し、proof タイプは calldata 第一バイトで区別される。この複雑度は単一チェーンとしては稀有だが、上場企業 Coinbase の単一障害点許容度は極めて低い。
-
Coinbase は sequencer の分散化を試みないが、コードは既に準備済み:
crates/consensus/service/src/actors/sequencer/conductor.rsは既に primary/standby failover の抽象を実装している。短期的に Coinbase が外部に sequencer を運営させることはない (sequencer revenue 2025 は $75M、Coinbase Base 事業の中核収益) が、コード層は ready である。 -
Smart wallet + Permissions + AgentKit は Coinbase の「コンシューマの王座」: この 3 点セットの組み合わせにより、Coinbase は web3 wallet 市場の distribution + UX + AI agent 入口を手中に収めた。Basenames と Base App と組み合わせれば、Coinbase の伝統的な取引所事業以外の第二成長エンジンとなる。
10.2 まだ完全に調査できていない事項
- Base sequencer の物理インフラ (AWS region、failover topology) — 公開データなし、SEC filing からの深掘りが必要
- Cannon (MIPS VM) の Base 上での真の dispute transaction 履歴 — 公開された etherscan dispute tx インデックスなし
- TEE PCR0 のオンチェーン allowlist の現値 — 直接 SystemConfigGlobal コントラクトの storage を照会する必要がある
- ZK prover の具体的な cluster size、proof generation 平均レイテンシ — Base は開示していない
- Base Azul 稼働後の最初の 1 週間の真の finality latency データ — レポート執筆日 (2026-05-13) がちょうど Azul 稼働日であり、データはまだ蓄積されていない
10.3 概览 との関係
概览 (projects/blockchain-research-2026-05/base/overview.md) が提供したのは Base の以下:
- プロジェクト戦略とタイムライン
- OP Stack と Superchain ガバナンス
- $TVL/MAU/sequencer revenue などの事業数字
- 他の L2 (Arbitrum/Optimism/zkSync) との高レベル比較
本レポート v2 (technology.md) が補完するのは:
- base/base Rust workspace の完全な crate マップと実際の LoC
- Flashblocks の真の実装経路 (file/line)
- 3 トラックフォールトプルーフのコントラクトインターフェースレベルの証拠
- Smart wallet の REPLAYABLE_NONCE_KEY 行番号
- L1 コントラクトの 99 回のアップグレード完全タイムライン
- 既知の脆弱性と未監査コンポーネント (Permissions)
両レポートを組み合わせると、戦略からコードまでの完全な深度をカバーする。
引用ソースリスト (タイプ別)
GitHub リポジトリ / ファイル
- base/base (本レポートの主要分析対象)
- base/op-enclave (TEE proof システム)
- base/basenames (Basenames コントラクト)
- base/contracts (Base L1 コントラクト)
- base/deployments (メインネットデプロイ履歴)
- base/paymaster (ERC-4337 paymaster)
- base/webauthn-sol (WebAuthn 検証ライブラリ)
- coinbase/smart-wallet (Smart Wallet コントラクト)
- coinbase/smart-wallet-permissions (Session keys)
- coinbase/agentkit (AI agent SDK)
- coinbase/onchainkit (React コンポーネントライブラリ)
- ethereum-optimism/optimism (上流 OP Stack)
- flashbots/rollup-boost (Flashblocks 上流)
- succinctlabs/op-succinct (ZK STF prover)
オンチェーントランザクション (Etherscan)
- 2025-03-05 fault proof upgrade tx: 0xac0db12a427a31ccbaf4a154cf6d5acf0b83c791a4bd7f93a54c9b150b9aa668
- 2025-04-23 Isthmus fault proof upgrade tx: 0x3baaa485746af0bb3d0a054a44a37c997b49b5528e0b58d351f5be05eacc2718
- 2025-11-21 U17 Jovian upgrade tx: 0x9b9aa2d8e857e1a28e55b124e931eac706b3ae04c1b33ba949f0366359860993
オンチェーンコントラクト (Etherscan / BaseScan)
- L1StandardBridge: 0x3154Cf16ccdb4C6d922629664174b904d80F2C35
- OptimismPortal: 0x49048044D57e1C92A77f79988d21Fa8fAF74E97e
- L2OutputOracle: 0x56315b90c40730925ec5485cf004d835058518A0
- SystemConfig: 0x73a79Fab69143498Ed3712e519A88a918e1f4072
- ProxyAdmin: 0x0475cBCAebd9CE8AfA5025828d5b98DFb67E059E
- Basenames Registry: 0xb94704422c2a1e396835a571837aa5ae53285a95
- Basenames RegistrarController: 0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5
- Basenames L1Resolver: 0xde9049636F4a1dfE0a64d1bFe3155C0A14C54F31
- Basenames L2Resolver: 0xC6d566A56A1aFf6508b41f6c90ff131615583BCD
- ERC-4337 EntryPoint v0.7 (all chains): 0x0000000071727De22E5E9d8BAf0edAc6f37da032
- Base Paymaster (Base Sepolia): 0xf5d253B62543C6Ef526309D497f619CeF95aD430
- DisputeGameFactory (OP Mainnet): 0xc641A33cab81C559F2bd4b21EA34C290E2440C2B
SEC Filings
- Coinbase 2024 10-K (filed 2025-02-13): SEC EDGAR 10-K
- Coinbase Q3 2025 10-Q: Q3 2025 PDF
- Coinbase Investor SEC filings index: https://investor.coinbase.com/financials/sec-filings/
公式 blog
- Fault proofs are now live on Base Mainnet
- Base reaches Stage 1 in Ethereum rollup decentralization
- Flashblocks Deep Dive: How we made Base 10x faster
- We’re making Base 10x faster with Flashblocks
- Scaling with Base Appchains
- Base’s Next Chapter: Everything We Announced At A New Day One
- Base’s Commitment to Decentralization with the Superchain
- How Base is making smart wallets the default
- Evolving wallets to bring a billion users onchain
- State of Wallets - Part 2
Succinct / Flashbots / Paradigm 技術 blog
- Base Adds ZK Proofs to Base Azul with SP1 - Succinct
- Introducing OP Succinct - Succinct
- Introducing OP Succinct Lite - Succinct
- Optimism Chooses Succinct - Succinct
- Introducing Rollup-Boost - Flashbots
- Reth Execution Extensions - Paradigm
L2BEAT / データページ
- Base Chain on L2BEAT
- Ethereum L2 Guide 2026 - Spotedcrypto
- Base 2025 transcript - RootData
- Base 2025 report card - Bitget News
メディア報道
- Base activates Flashblocks - The Block
- Base cuts block times to 0.2 seconds - The Block
- Coinbase-incubated Base adopts Succinct - The Block
- Base sequencer handoff failure - The Block
- Base Outage August 2025 - CoinDesk
- Coinbase 2023-09 outage - Decrypt
- Coinbase Base outage major - Cointelegraph
- Snipers Pocket $1.3M on Pollak Creator-Coin
- Coinbase Smart Wallet 1M Users
- Coinbase Q1 2026 earnings - CNBC
- Yellow.com Base ZK Proofs $12B
学術と仕様
- arxiv 2405.03183 - Impact of EIP-4844 (IEEE 論文)
- OP Stack Specification
- Base Specification
- ERC-4337 Account Abstraction
- RIP-7212 secp256r1 precompile
- ENSIP-10 CCIP-Read
監査報告
- Cantina Coinbase Smart Wallet portfolio
- Code4rena 2024-03 Coinbase contest
- Coinbase Bounty on Cantina
- Optimism on Immunefi
Coinbase Developer Platform
- CDP Paymaster Masterclass
- Base docs - Gasless transactions
- Base docs - Account abstraction
- Base docs - Contract addresses
- Base Account overview
Optimism docs
- Permissionless Fault Proofs and Stage 1
- Fault Proofs explainer
- Privileged Roles in OP Stack
- Upgrade 17 - Jovian
- Upgrade 14 MT-Cannon and Isthmus
(レポート終了)