A-1 bytecode
A-1 bytecode
この項目では、live V1 テストネットにデプロイされている CAW の各コントラクトの実行コードが、公開ソースをコンパイルした結果と一致するかを確かめます。エクスプローラの「検証済み」表示には頼りません――というより、これらの契約は Basescan 等で未検証です。だからこそ、自分の手元で同じものをコンパイルし、チェーン上のコードと突き合わせる。誰かの説明ではなく、再現できる証拠で語ります。
公開されている「レシピ」(ソースコード)と、実際に出てきた「料理」(チェーン上で動いているコード)が同じものか――それを確かめる項目です。私たちはレシピを取り寄せ、自分の手で同じ手順どおりに調理し(コンパイルし)、出来上がりを実際の料理とバイト単位で見比べました。
→
自分でコンパイル同じ手順で
→
チェーン上のコード= 完全一致
結果は バイト単位でぴたり一致。しかも参照アドレス(immutable)を伏せた「コード本体」だけでなく、末尾のメタデータ(ソースのハッシュ)まで含めて一致しました。つまり「動いているコード=公開されているソース」を、エクスプローラのバッジに頼らず自分のキッチンだけで確かめた、ということです。
1. 主張(検証対象)
live V1 の各コントラクトの実行コード(runtime bytecode)が、公開リポジトリ GilgameshCaw/Caw のソースをコンパイルした結果と一致すること。ブロックエクスプローラのソース検証機能には依存せず(実際これらは未検証)、第三者が同じ手順で同じハッシュに到達できる、再現可能な形で証明します。
2. 検証方法
ビルド設定は、デプロイ当時の hardhat.config.js と、リポジトリにコミットされた solidity/package-lock.json(依存を版固定)に準拠します。
| 項目 | 値 |
|---|---|
| solc | 0.8.22 |
| optimizer | 有効・runs = 1 |
| viaIR | true |
| evmVersion | paris |
| 依存 | OZ 4.9.6 / LayerZero oapp-v2 2.3.44 ほか(lock 固定) |
手順は4つです。
ローカルでコンパイル
各コントラクトを上記設定でコンパイルし、deployedBytecode と immutableReferences(immutable が置かれるバイト位置)を取得する。
canonical ハッシュを算出
immutable 領域(各32バイト)をゼロ化して、keccak256 を出す。
オンチェーンを同じ形に
実コードを取得し、同じ immutable 領域でゼロ化して keccak256 を出す。
突き合わせる
両者のハッシュが一致すれば、コードは公開ソースそのもの。今回はメタデータ込みの値(full)まで一致しました。
なぜ immutable 領域をゼロ化するのか。immutable 変数はデプロイ時に実行コードへ焼き込まれ、ソースには無い実値(例:LayerZero エンドポイントアドレス)が入ります。そのため生のバイトコードは必ず差が出る。コードそのものの同一性を見るには、この領域を両側で除外して比べる必要があります。なお evmVersion は paris でした――既定の shanghai(PUSH0 命令あり)でビルドすると長さがズレ、paris でのみ長さ・メタデータまで完全一致したことから確定できます。
3. 判定
a26e0063、Marketplace のみ後発 d5dfc730。CAW token は外部の既存契約で対象外。結果はこうなりました。
- 一致 コアのプロトコル契約 12型(CawActions・CawProfileL2・CawActionsArchive・CawChallengeRelay・CawProfile・CawClientManager・Minter・Quoter・URI・BuyAndBurn・FontDataA/B)が、L1/L2/L2b の全インスタンスで byte 完全一致。ソースは commit
a26e0063。 - 一致 CawProfileMarketplace は後発 commit
d5dfc730(監査修正 H-15/H-17 等の後に増分再デプロイされた版)から byte 完全一致。デプロイは単一コミットではなく増分で、各契約は実デプロイ時のソースに対応します。 - 対象外 CAW token(MintableCaw)は、deploy.js に「再デプロイしない既存契約」と明記された外部の既存トークンです。ソースツリーの一部ではないため、本項目のソース照合の対象外(=一致しないのが正しい)。本物の CAW は別途の既存 ERC20。
実プロトコルのコントラクトは、エクスプローラ未検証であっても、自前のコンパイルだけで全件 byte 完全一致を確認しました。
4. receipt(公開証明)
誰でも再現できるよう、コンパイルで得た canonical keccak(immutable ゼロ化後の keccak256。メタデータ込み)を残します。同じ型は L1/L2/L2b で同じハッシュを共有します(同一ソース・同一設定のため)。
| コントラクト | チェーン | ソース | canonical keccak256 |
|---|---|---|---|
| CawActions | L1/L2/L2b | a26e0063 | 0x050b3a9f200b3b75f4882445c9a6d8d147a37fecdb8d5f693c54d974f3931caf |
| CawProfileL2 | L1/L2/L2b | a26e0063 | 0xeef755f4f5762278d8bf682f9be75e8641bc824de647f7dee7d76fafb85a8e71 |
| CawActionsArchive | L2/L2b | a26e0063 | 0xbfd02e0849825a47b5d8f33b1c340285f7af66aaf463d732b0d20bad18c935f1 |
| CawChallengeRelay | L2/L2b | a26e0063 | 0xb6f20c1dcd4689f37a0b0a4d9e69c4c4d47336d5fd1d8168927a17eee3e4cdef |
| CawProfile | L1 | a26e0063 | 0x875d8d6165ae4e0388767362eb9b4424339465068227431e30318a4cc20f347c |
| CawClientManager | L1 | a26e0063 | 0x2939ac4da5aa89b0025a3b77e3c290dfae6df02c9d48888b3e9e02e9744ad71e |
| CawProfileMinter | L1 | a26e0063 | 0x3217e3d61c28d861492351d2a859d4704c655de9970d0916ee634fc3a480668e |
| CawProfileQuoter | L1 | a26e0063 | 0xbaf0af4f45d1125d67f4b58192a48f2a0cf1ef7bd9b9bf4cf54373d19d379e44 |
| CawProfileMarketplace | L1 | d5dfc730 | 0x84642479dbb6dbd680e69118f0e0a5bf7ad2f87a8ff53bff452f8f72f87712d5 |
| CawProfileURI | L1 | a26e0063 | 0x3c715a2d21bbc1e74726a3b151005ff3026ee0fc8a6ac47d975660105bac499b |
| CawBuyAndBurn | L1 | a26e0063 | 0xc6992111593c41bc646d6edc3da5190f7241fd227b5ac5e1079d7af1f58daaf3 |
| CawFontDataA | L1 | a26e0063 | 0xb80eb0f102c1aef01852d6fdf4fac3a5ecda97f523936030a7b40e1a9c98a347 |
| CawFontDataB | L1 | a26e0063 | 0x49ab78a2394dd9db9ca1061cd8f5ef17cc1f5e573379a7262742f11f3e5aadf4 |
再現は、実コードを取得して同じ immutable 領域をゼロ化し keccak256 を取るだけです。自分のノードと同じ ethers v6(node) 一発版(getCode→マスク→keccak256・貼り付け不要)を、下のツールの「コマンドで確認」にコピー安全な形で用意しています。出力が 0x050b3a9f…931caf と一致すれば OK。
5. 注記・限界
チェーン対応:L1 = Sepolia / L2 = Base Sepolia / L2b = Arbitrum Sepolia。
a26e0063 時点のソースのまま(アドレス不変=再デプロイされていない)で、Marketplace のみ後の d5dfc730(H-15/H-17 等の監査修正を反映)で独立に更新・再デプロイされていました。各契約のバイトコードを、それぞれの実デプロイ・コミットに対して照合しています。
この項目(A-1)が扱うのは「実行コードの同一性」です。所有権の状態(A-2)、プロキシ構造(A-3)、所有権移転の履歴(A-4)、immutable 値の正当性(A-5)は、台帳の別項目で扱います。
証拠が出るまで、検証済みとは書かない。
This item checks whether the runtime code of each CAW contract deployed on the live V1 testnet matches the result of compiling the public source. We do not rely on an explorer’s “Verified” badge — in fact, these contracts are unverified on Basescan and the like. So we compile the same thing ourselves and diff it against the on-chain code. We speak with reproducible evidence, not with someone’s explanation.
Is the published “recipe” (the source code) the same as the “dish” actually served (the code running on-chain)? That is what this item checks. We took the recipe, cooked it ourselves with the exact same steps (compiled it), and compared the result with the real dish byte for byte.
→
we compilesame steps
→
on-chain code= exact match
The result was an exact byte-for-byte match — and not only the “code body” with the reference addresses (immutables) masked, but the trailing metadata (a hash of the source) as well. So “the code that runs = the published source,” confirmed in our own kitchen without leaning on an explorer’s badge.
1. Claim (what is verified)
That the runtime bytecode of each live V1 contract matches the result of compiling the source in the public repository GilgameshCaw/Caw. Without relying on any block-explorer source-verification feature (they are in fact unverified), we prove it reproducibly — anyone can follow the same steps and arrive at the same hash.
2. Method
The build settings follow the deploy-era hardhat.config.js and the solidity/package-lock.json committed to the repository (which pins dependency versions).
| Setting | Value |
|---|---|
| solc | 0.8.22 |
| optimizer | enabled, runs = 1 |
| viaIR | true |
| evmVersion | paris |
| dependencies | OZ 4.9.6 / LayerZero oapp-v2 2.3.44, etc. (lock-pinned) |
There are four steps.
Compile locally
Compile each contract with the settings above and obtain its deployedBytecode and immutableReferences (the byte offsets where immutables sit).
Compute the canonical hash
Zero out the immutable regions (32 bytes each) and take the keccak256 hash.
Normalize the on-chain code the same way
Take the live code, zero out the same immutable regions, and take its keccak256.
Diff them
If the two hashes match, the code is the public source itself. Here even the metadata-included value (full) matched.
Why zero out the immutable regions? Immutable variables are baked into the runtime code at deploy time, holding real values that do not exist in the source (e.g. the LayerZero endpoint address). So the raw bytecode will always differ. To compare the identity of the code itself, you must exclude these regions on both sides. The evmVersion was paris — building with the default shanghai (which uses the PUSH0 opcode) shifts the length; only paris reproduced the exact length and metadata, which pins the setting.
3. Verdict
a26e0063, Marketplace alone from the later d5dfc730. The CAW token is a pre-existing external contract, out of scope.The result was as follows.
- match The 12 core protocol types (CawActions, CawProfileL2, CawActionsArchive, CawChallengeRelay, CawProfile, CawClientManager, Minter, Quoter, URI, BuyAndBurn, FontDataA/B) are a byte-for-byte match on every instance across L1/L2/L2b. Source: commit
a26e0063. - match CawProfileMarketplace is a byte-for-byte match against the later commit
d5dfc730(the version redeployed after audit fixes H-15/H-17, etc.). The deployment is incremental, not a single commit — each contract corresponds to its actual deploy-time source. - out of scope The CAW token (MintableCaw) is a pre-existing external token, explicitly marked in deploy.js as a contract that is “not redeployed.” It is not part of the source tree, so it is outside this item’s source check (not matching is correct). The real CAW is a separate existing ERC20.
The real protocol contracts — even where the explorer shows them unverified — were confirmed as a byte-for-byte match using only our own compile.
4. Receipt (public proof)
So anyone can reproduce it, we leave the canonical keccak from compiling (keccak256 after immutable zeroing, metadata included). The same type shares the same hash across L1/L2/L2b (same source, same settings).
| Contract | Chain | Source | canonical keccak256 |
|---|---|---|---|
| CawActions | L1/L2/L2b | a26e0063 | 0x050b3a9f200b3b75f4882445c9a6d8d147a37fecdb8d5f693c54d974f3931caf |
| CawProfileL2 | L1/L2/L2b | a26e0063 | 0xeef755f4f5762278d8bf682f9be75e8641bc824de647f7dee7d76fafb85a8e71 |
| CawActionsArchive | L2/L2b | a26e0063 | 0xbfd02e0849825a47b5d8f33b1c340285f7af66aaf463d732b0d20bad18c935f1 |
| CawChallengeRelay | L2/L2b | a26e0063 | 0xb6f20c1dcd4689f37a0b0a4d9e69c4c4d47336d5fd1d8168927a17eee3e4cdef |
| CawProfile | L1 | a26e0063 | 0x875d8d6165ae4e0388767362eb9b4424339465068227431e30318a4cc20f347c |
| CawClientManager | L1 | a26e0063 | 0x2939ac4da5aa89b0025a3b77e3c290dfae6df02c9d48888b3e9e02e9744ad71e |
| CawProfileMinter | L1 | a26e0063 | 0x3217e3d61c28d861492351d2a859d4704c655de9970d0916ee634fc3a480668e |
| CawProfileQuoter | L1 | a26e0063 | 0xbaf0af4f45d1125d67f4b58192a48f2a0cf1ef7bd9b9bf4cf54373d19d379e44 |
| CawProfileMarketplace | L1 | d5dfc730 | 0x84642479dbb6dbd680e69118f0e0a5bf7ad2f87a8ff53bff452f8f72f87712d5 |
| CawProfileURI | L1 | a26e0063 | 0x3c715a2d21bbc1e74726a3b151005ff3026ee0fc8a6ac47d975660105bac499b |
| CawBuyAndBurn | L1 | a26e0063 | 0xc6992111593c41bc646d6edc3da5190f7241fd227b5ac5e1079d7af1f58daaf3 |
| CawFontDataA | L1 | a26e0063 | 0xb80eb0f102c1aef01852d6fdf4fac3a5ecda97f523936030a7b40e1a9c98a347 |
| CawFontDataB | L1 | a26e0063 | 0x49ab78a2394dd9db9ca1061cd8f5ef17cc1f5e573379a7262742f11f3e5aadf4 |
Reproduction: fetch the live code, zero out the same immutable regions, and take keccak256. The same ethers v6 (node) one-liner (getCode → mask → keccak256, no paste) is provided copy-safe under “CLI” in the tool below; the printed hash should equal 0x050b3a9f…931caf.
5. Notes & limits
Chain mapping: L1 = Sepolia / L2 = Base Sepolia / L2b = Arbitrum Sepolia.
a26e0063 source (their addresses are unchanged — i.e. not redeployed), while only the Marketplace was independently updated and redeployed at the later d5dfc730 (reflecting audit fixes such as H-15/H-17). We reconcile each contract’s bytecode against its actual deploy commit.
What this item (A-1) covers is the identity of the runtime code. Ownership state (A-2), proxy structure (A-3), ownership-transfer history (A-4), and the legitimacy of the immutable values (A-5) are handled in other items of the ledger.
Until the evidence is in, we don’t write “verified.”






