B-3 delegate
B-3 delegate
peer が二度と動かせないこと(B-1)は、LayerZero 設定のロックの一部にすぎません。各 OApp にはもう一つの権限――LayerZero の EndpointV2 上で送受信ライブラリや DVN などのセキュリティ設定を調整できる delegate(委任先)――があります。この項目では、live V1 の全 OApp の現 delegate を読み出して「誰が握っているか」を確かめ、さらに、この権限が onlyOnce ロックされているかをソースとオンチェーンの両面から確認します。
0x6EDCE…f10f)を指していることは A-5 で確認済みです(endpoint() を持つ OApp で 8/8。本ページの delegate 検証は endpoint()・peers() を持つ 7 OApp が対象で、母数の違いはこの基準差によるものです)。B-1 は「配線を後から動かせない」ことでした。でも配線とは別に、セキュリティ設備(メッセージを検証する見張り)を設定し直せる「管理人」のような役(delegate)がいます。delegate を持つ OApp すべてで、その管理人の鍵を今だれが持っているかを読み出しました。答えは「owner(deployer の単一 EOA)と同じ一本」。
→
7/7 = owner単一EOA
→
onlyOnce 非適用owner は A-2 と同根
この『管理人』が扱うのは、見張り(DVN)の入れ替えや詰まったメッセージの復旧など、運用中に更新される設備です。peer(配線)と違い、ここをロックすると見張りが壊れても交換できなくなります。LayerZero の標準設計でも、ここは固定せず owner が調整できるようになっています。読み出した結果、その鍵を持つのは A-2 で確認済みの owner と同じ一本でした。
1. 主張(検証対象)
live V1 の各 OApp について、LayerZero EndpointV2 に登録された現 delegate を特定すること。そして、setDelegate が B-1 の peer のように onlyOnce ロックされているかをソースで確認し、変更権限を誰が持つかをオンチェーンとあわせて確かめること。本項目は「delegate がロックされている」と主張するものではなく、現 delegate・ロック状態・変更権限の所在という観測結果を開示するものです。
2. 検証方法
OApp を特定し、delegate の保存先を確認
OApp を継承するのは 3種(CawProfileL2/CawChallengeRelay/CawActionsArchive)=計 7インスタンス。CawProfile(L1本体 0x9CEf…274f)は endpoint()/peers() を持たない非 OAppで、CawActions・Quoter と同様 LayerZero の delegate を持ちません(オンチェーンで delegates()=ゼロを確認)。delegate は各 OApp ではなく LayerZero EndpointV2 の mapping(address oapp => address delegate) public delegates に保存され、OApp のコンストラクタが endpoint.setDelegate(_delegate) でデプロイ時に設定します。
delegates() と owner() を全数オンチェーンで読む
3チェーン(Sepolia 40161 / Base Sepolia 40245 / Arbitrum Sepolia 40231)の全 7 OApp について、LayerZero EndpointV2 の delegates(oapp) を読み、併せて各 OApp の owner() も読んで突き合わせる。
ソースで「ロックされているか」を確認
setPeer は CAW が onlyOnce にオーバーライドして配線済み peer を不可逆ロックしていました(B-1)。一方 setDelegate が同様にロックされているかをソースで確認――どの CAW 契約も setDelegate を再定義しておらず、OAppCore の public onlyOwner のままでした。
3. 判定
onlyOnce ロックされず public onlyOwner のまま(LayerZero 標準・CAW は再定義なし)で、変更権限は owner に帰着する。setDelegate は onlyOnce でロックされておらず、public onlyOwner のまま(LayerZero 標準・CAW は再定義なし)。delegate が扱うのは DVN 等のセキュリティ設定で、ロックすると差し替え・復旧ができなくなる。変更権限は A-2 の owner と同一鍵に帰着する。- 7/7 一致 delegate を持つ OApp は全 7 件で delegate = owner = deployer EOA
0xF71338…4a95。別アドレスが混じる例外は1件もなし。 - 標準どおり
setDelegateはpublic onlyOwner(LayerZero 標準)で、CAW は再定義していない。delegate が扱うのは DVN・ライブラリ等のセキュリティ設定と詰まりメッセージの復旧で、ロックすると差し替え・復旧ができなくなる。 - 変更権限 変更できるのは owner のみで、その owner は A-2 と同一の単一 EOA。新たな信頼の前提は増えておらず、mainnet で multisig 移管/renounce すればこの権限も統治下に入る。
B-1 の setPeer は CAW が onlyOnce にオーバーライドし、配線済み peer をowner でも張替不能にしました。peer は「どのチェーンのどの契約に繋ぐか」という静的なトポロジで、B-1 で onlyOnce により張替不能であることを確認しました。
一方 setDelegate が握るのは、DVN(検証者ネットワーク)・送受信ライブラリ・確認数といった 運用中に更新が必要なセキュリティ設定と、詰まった受信メッセージの復旧(skip / clear / nilify / burn)です。これをロックすると、DVN が停止・危殆化しても差し替えられず、経路が壊れても復旧できません。LayerZero の標準設計(OAppCore の public onlyOwner)は delegate を調整可能なままにしており、CAW も setDelegate を再定義していません。CAW は peer のみ onlyOnce で固定し、delegate は固定していません。
変更できるのは owner のみで、その owner は A-2/A-4 で開示済みの同一 EOA です。
onlyOnce ロックされず public onlyOwner のまま(LayerZero 標準・CAW は再定義なし)。変更権限は「owner 鍵」一点に帰着し、それは既に A-2 で開示済み。mainnet で multisig 移管/renounce が実行されれば、この変更権限もその統治下に入ります。なお本項目のツール用に全 OApp の実値を取得した際、
CawProfile(L1本体)が非 OApp で delegate を持たないことを再確認し、検証対象を 7 OApp に厳密化しました(当初の「8」表記を修正)。判定の向き(全数 owner 一致・新規リスクなし)は変わりません。本判定は読み出しブロック時点のスナップショット(2026-06-22)。delegate は調整可能な設定ですが、現状(単一 EOA・新規リスクなし)と、setDelegate が public onlyOwner のまま(onlyOnce 非適用)であることを確認済みのため、本項目は検証済としています。4. receipt(公開証明)
全 OApp の delegate(LayerZero EndpointV2 から読み出し)と owner を並べた照合結果です(OApp 7件+参考として非OApp 1件)。
| # | OApp(チェーン) | delegate(LZ EndpointV2) | owner | 判定 |
|---|---|---|---|---|
| 1 | CawProfile(L1本体・Sepolia) | 0x0000…0000 | 0xF71338…4a95 | 対象外(非OApp) |
| 2 | CawProfileL2_L1 mirror(Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 3 | CawProfileL2_L2(Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 4 | CawChallengeRelay_L2(Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 5 | CawActionsArchive_L2(Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 6 | CawProfileL2_L2b(Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 7 | CawChallengeRelay_L2b(Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
| 8 | CawActionsArchive_L2b(Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | 一致 |
※ #1 CawProfile(L1本体 0x9CEf…274f)は OApp を継承せず LayerZero EndpointV2 に delegate 登録が無いため、delegate 検証の対象外。owner は 0xF71338…4a95 で A-2 と同根です。
対象:deployer EOA 0xF71338f3eAa483aA66125598B09BA1988e694a95。LayerZero EndpointV2(全チェーン共通)0x6EDCE…f10f。
再現は、LayerZero EndpointV2 の delegates(oapp) を読み、各 OApp の owner() と突き合わせるだけです。ロックの有無はソース側で確認します。
cast call 0x6EDCE65403992e310A62460808c4b910D972f10f "delegates(address)(address)" <OApp> --rpc-url <チェーンのRPC> cast call <OApp> "owner()(address)" --rpc-url <チェーンのRPC> # 7/7(OApp 全数)で delegate == owner == 0xF71338…4a95(一本化を確認)。 # ロック確認はソース側:setDelegate は public onlyOwner(LayerZero 標準・CAW は再定義なし)。 7/7 一致(delegate=owner=単一EOA)/ setDelegate は public onlyOwner のまま(変更権限は owner)
delegates(oapp) と owner() を読むだけ。開いて「検証する」を押すと、3チェーンの OApp 7件について delegate と owner の両方が同一の期待 EOA を返すか一括照合します。塞がれる場合はツール内「コマンドで確認」へ(Chrome で出ないときは Edge かシークレットウィンドウでも)。さらに期待 EOA を編集でき、「わざと壊す」で実際に赤くなる(=常に合格ではない)ことや、生の返り値・叩いたリクエスト、開発者ツールの Network タブで実通信を確認できます。非OApp の CawProfile(L1本体)は対象外として表示します。
5. 注記・限界
delegate が握る権限は、いずれも運用中に更新が必要なものです。LayerZero EndpointV2 を介した送受信ライブラリの指定、DVN・executor・確認数などの設定変更、さらに詰まった受信メッセージの skip / clear / nilify / burn。これらは peer ルーティング(B-2)とは別系統で、LayerZero 標準では調整可能に保たれるメッセージング設定面です。
L1 上のミラー CawProfileL2_L1(bypassLZ=true)も OApp なので、コンストラクタで delegate が設定済みです。LayerZero メッセージは流しませんが LayerZero EndpointV2 には登録されており、本項目でも delegate=owner を確認しています(A-5 で bypassLZ=true を確認済み)。
本項目はある block 時点のスナップショットです。delegate は性質上 owner が調整可能なので、B-1 の immutable な結論とは種類が異なります(恒久ロックの保証ではなく、現状=単一 EOA・新規リスクなしの確認)。owner = deployer EOA である点は A-2/A-4 と同根で、mainnet で multisig 移管/renounce が実行されれば、delegate 調整権限もその統治下に入ります。
混ぜないことが、煽らないことであり、隠さないことでもある。
A peer being un-movable (B-1) is only part of locking down the LayerZero config. Each OApp carries another role — the delegate, the address authorized on the LayerZero EndpointV2 to adjust the messaging security config (send/receive libraries, DVNs, and so on). Here we read the current delegate of every live V1 OApp to see who holds it, and we check — from both source and on-chain — whether this authority is onlyOnce-locked.
0x6EDCE…f10f) was confirmed in A-5 (8/8 among OApps that carry endpoint(); this page’s delegate check covers the 7 OApps with endpoint()/peers(), so the different count is just this difference in basis).B-1 was “the wiring can’t be moved later.” But separate from the wiring, there is a “superintendent” role (the delegate) that can re-configure the security equipment — the guards that verify messages. On every delegate-carrying OApp we read who currently holds that key. The answer: “the same single key as the owner (the deployer’s single EOA).”
→
7/7 = ownersingle EOA
→
not onlyOnce-lockedowner from A-2
What this “superintendent” governs — swapping out the guards (DVNs), recovering stuck messages — is equipment that is updated during operation. Unlike the peer (the wiring), if this were locked you could no longer replace a guard that breaks. LayerZero’s standard design leaves it adjustable by the owner rather than fixed. We read who holds the key — and it is the same single key as the owner already disclosed in A-2.
1. Claim (what is verified)
To identify the current delegate registered on the LayerZero EndpointV2 for each live V1 OApp; to check in source whether setDelegate is onlyOnce-locked like the peer in B-1; and to identify who holds the change authority. This item does not assert “the delegate is locked”; it discloses the observed current delegate, lock status, and who can change it.
2. Method
Identify the OApps and where the delegate lives
Three contracts inherit OApp (CawProfileL2 / CawChallengeRelay / CawActionsArchive) = 7 instances. CawProfile (the L1 base, 0x9CEf…274f) has no endpoint()/peers() and is a non-OApp; like CawActions and Quoter it carries no LayerZero delegate (confirmed on-chain: delegates() = zero). The delegate is stored not on each OApp but on the LayerZero EndpointV2’s mapping(address oapp => address delegate) public delegates, set at deploy time by the OApp constructor via endpoint.setDelegate(_delegate).
Read delegates() and owner() for every instance on-chain
For all 7 OApps across the three chains (Sepolia 40161 / Base Sepolia 40245 / Arbitrum Sepolia 40231), read the LayerZero EndpointV2’s delegates(oapp) and also read each OApp’s owner(), then reconcile.
Check in source whether it is “locked”
CAW overrode setPeer to onlyOnce, making configured peers irreversible (B-1). We check whether setDelegate is locked the same way — and no CAW contract redefines setDelegate; it remains OAppCore’s public onlyOwner.
3. Verdict
setDelegate is not onlyOnce-locked and remains public onlyOwner (the LayerZero default; CAW does not redefine it). The delegate governs security config (DVNs and the like); if locked, those could not be swapped or recovered. The change authority reduces to the same key as A-2‘s owner.- 7/7 match all 7 delegate-carrying OApps have delegate = owner = deployer EOA
0xF71338…4a95. Not a single instance carries a different address. - as standard
setDelegateispublic onlyOwner(the LayerZero standard) and CAW does not redefine it. The delegate governs security config (DVNs, libraries) and recovery of stuck messages; if locked, those could not be swapped or recovered. - change authority Only the owner can change it, and that owner is the same single EOA as A-2. No new trust assumption is added; a mainnet multisig migration / renouncement would bring this authority under that governance too.
B-1’s setPeer was overridden by CAW to onlyOnce, making a configured peer un-replaceable even by the owner. A peer is static topology — “which contract on which chain to connect to” — locked by onlyOnce as confirmed in B-1.
What setDelegate governs, by contrast, is security config that needs updating during operation — DVNs (the verifier network), send/receive libraries, confirmation counts — plus recovery of stuck inbound messages (skip / clear / nilify / burn). Lock that, and you could not swap a stalled or compromised DVN, nor recover a broken pathway. LayerZero’s standard design (OAppCore’s public onlyOwner) leaves the delegate adjustable, and CAW does not redefine setDelegate. CAW locks only the peer with onlyOnce and leaves the delegate adjustable.
The change authority is the single point “only the owner can change it” — and that owner is the same EOA already disclosed in A-2 / A-4.
onlyOnce-locked and remains public onlyOwner (the LayerZero standard; CAW does not redefine it). The change authority reduces to the single “owner key,” already disclosed in A-2; a mainnet multisig migration / renouncement would bring this change authority under that governance too. Note: while fetching every OApp’s live values for this item’s tool, we re-confirmed that
CawProfile (the L1 base) is a non-OApp with no delegate, and tightened the scope to 7 OApps (correcting an earlier “8”). The direction of the verdict (all owner-matched, no new risk) is unchanged. This verdict is a snapshot at the read block (2026-06-22). The delegate is an adjustable setting, but the current state (single EOA, no new risk) and that setDelegate remains public onlyOwner (no onlyOnce) are confirmed, so this item is marked verified.4. Receipt (public proof)
The reconciliation of every OApp’s delegate (read from the LayerZero EndpointV2) against owner (7 OApps, plus one non-OApp for reference).
| # | OApp (chain) | delegate (LZ EndpointV2) | owner | Result |
|---|---|---|---|---|
| 1 | CawProfile (L1 base, Sepolia) | 0x0000…0000 | 0xF71338…4a95 | out of scope (non-OApp) |
| 2 | CawProfileL2_L1 mirror (Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 3 | CawProfileL2_L2 (Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 4 | CawChallengeRelay_L2 (Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 5 | CawActionsArchive_L2 (Base Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 6 | CawProfileL2_L2b (Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 7 | CawChallengeRelay_L2b (Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
| 8 | CawActionsArchive_L2b (Arb Sepolia) | 0xF71338…4a95 | 0xF71338…4a95 | match |
* #1 CawProfile (the L1 base, 0x9CEf…274f) does not inherit OApp and has no delegate registered on the LayerZero EndpointV2, so it is out of scope for the delegate check. Its owner is 0xF71338…4a95, sharing its root with A-2.
Target: deployer EOA 0xF71338f3eAa483aA66125598B09BA1988e694a95. LayerZero EndpointV2 (shared on all chains) 0x6EDCE…f10f.
To reproduce, read the LayerZero EndpointV2’s delegates(oapp) and reconcile it with each OApp’s owner(). The lock status is checked in source.
cast call 0x6EDCE65403992e310A62460808c4b910D972f10f "delegates(address)(address)" <OApp> --rpc-url <chain RPC> cast call <OApp> "owner()(address)" --rpc-url <chain RPC> # 7/7 (all OApps): delegate == owner == 0xF71338…4a95 (consolidation confirmed). # lock check is in source: setDelegate is public onlyOwner (LayerZero standard; CAW does not redefine it). 7/7 match (delegate=owner=single EOA) / setDelegate remains public onlyOwner (change authority: owner)
▶ Reproduce this check in your browser (new window)
Just reads delegates(oapp) and owner(). Press Verify and it checks, for all 7 OApps across 3 chains, whether both the delegate and the owner return the same expected EOA. If blocked, use the in-tool “confirm via command” (or try Edge / a private window). You can edit the expected EOA; the sanity-break button actually turns it red (not always-pass), and you can check the raw returns, the requests made, and the real traffic in the DevTools Network tab. The non-OApp CawProfile (L1 base) is shown as out of scope.
5. Notes & limits
The powers the delegate holds are all things that need updating during operation. Through the LayerZero EndpointV2 it can set the send/receive libraries, change config (DVNs, executor, confirmation counts), and skip / clear / nilify / burn stuck inbound messages. These are a messaging-config surface separate from peer routing (B-2), kept adjustable in the LayerZero standard.
The L1 mirror CawProfileL2_L1 (bypassLZ=true) is also an OApp, so its delegate was set at construction. It carries no LayerZero traffic but is registered on the LayerZero EndpointV2, and here too we confirmed delegate = owner (its bypassLZ=true was confirmed in A-5).
This item is a snapshot at a given block. Because the delegate is adjustable by nature, it differs in kind from B-1’s immutable conclusion (it is not a permanent-lock guarantee, but a confirmation that the current state is a single EOA with no new risk). That owner = deployer EOA shares its root with A-2 / A-4; once a multisig migration / renouncement is executed on mainnet, the delegate-adjust authority falls under that governance too.
Keeping them apart is how we avoid both false alarm and false comfort.






