Workspace IndexDev Notes › LayerZero — the default verifier is a trust assumption nobody wrote down

#46PoC

LayerZero — the default verifier is a trust assumption nobody wrote down

LayerZero moves arbitrary messages between chains and lets the application pick its own verifier set. That is the real feature and the real trap: skip the choice and you have still made one, and nothing in your codebase records who you are now trusting.

Thirty minutes, two testnets. Deploy one OApp and send a single message round trip; then run lz:oapp:config:get and write one line answering the only question that matters — who am I trusting right now. Paste that output into the README, because it is the trust assumption and it lives in configuration rather than code. Optional third step: take the four-way split ATLAS publishes (matching, clearing, settlement, risk) into the settlement design notes. Sources: layerzero.network and docs.layerzero.network; ATLAS announced 2026-08-26, running on the Zero L1 shipped in February, published at p50 sub-millisecond and p99 2.641ms under vendor stress testing, part of fees routed to ZRO buyback and burn, launch stated for this autumn, with Citadel Securities, DTCC, ARK Invest and ICE named. Vendor figures and an unreleased product — confirm before relying on any of it.

Why

The product is not a bridge, and reading it as one hides the interesting part. LayerZero is a message layer: an application inherits OApp and sends an arbitrary payload from its contract on one chain to its contract on another, with OFT and ONFT as the token-shaped wrappers over that. The design choice underneath is that verification is modular — a Decentralized Verifier Network set that the application selects and composes, rather than a security assumption fixed by the protocol.

That modularity is genuinely better and it relocates a decision onto you, silently. A protocol with fixed security has one trust assumption and everyone inherits it, for good and ill. A protocol with selectable verification has as many assumptions as there are applications — and an application that never makes the choice does not escape it, it accepts a default. The failure is not that the default is bad. It is that the default is invisible: nothing in the repository says who verifies your messages, so the most security-relevant fact about the integration is absent from every code review of it.

Which is why the practical habit is worth more than the tutorial. Run the config query after the first deploy and paste the output where people read it. The question who am I trusting right now has an answer at every moment; the only variable is whether anyone has written it down. Compare third-party-blast-radius, which asks the same thing about dependencies, and storage-collision-admin-takeover, where the load-bearing fact also lived outside any single file.

The second trap is a silent one, and worth stating precisely. The sender pre-pays destination gas by encoding it in options. Under-provision it and the send looks successful while execution fails on the destination — a message that appears delivered and did nothing. Any production path over this needs a retry story written before it is needed, because the failure does not announce itself at the call site.

And the strategic note belongs to a different card. ATLAS moves LayerZero from infrastructure to market infrastructure, which changes who its competitors are — no longer Wormhole and Axelar but chains that own an exchange. headless-exchange-engines carries that argument. What belongs here is the engineering residue: the four-way split ATLAS publishes — matching, clearing, settlement, risk — is a usable module boundary, and separating risk from settlement is the part worth copying whether or not the product is ever used.

How it works

The first contact, and the three lines that matter

Endpoint address, destination EID, and options encoding — everything else is ordinary Solidity.

import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";

contract PingPong is OApp {
    using OptionsBuilder for bytes;
    string public lastMessage;

    constructor(address _endpoint, address _owner) OApp(_endpoint, _owner) {}

    function send(uint32 dstEid, string calldata text) external payable {
        bytes memory payload = abi.encode(text);
        // destination gas is chosen by the sender — the UX core and the first trap
        bytes memory options = OptionsBuilder.newOptions()
            .addExecutorLzReceiveOption(80_000, 0);
        _lzSend(dstEid, payload, options, MessagingFee(msg.value, 0), payable(msg.sender));
    }

    function _lzReceive(
        Origin calldata, bytes32, bytes calldata payload, address, bytes calldata
    ) internal override {
        lastMessage = abi.decode(payload, (string));
    }
}
npx hardhat lz:oapp:config:get     # read the defaults — this is the trust assumption
npx hardhat lz:oapp:send --dst-eid 40161 --text "hello"

The two traps, and why both are silent

Trap What it looks like Why nothing catches it
Under-provisioned destination gas Send succeeds, destination execution fails The failure is on another chain; the call site returns fine
Untouched DVN configuration Everything works Nothing in the repo names the verifier, so review has nothing to object to

Both are the same class: a decision made by omission, recorded nowhere. The habit that fixes both costs one command and one paragraph in a README.

Cost, and where it varies

Component Paid to Note
Source-chain gas The source chain Ordinary
Destination execution gas Pre-paid at send Quoted at send time — a congested destination moves the quote a lot
DVN fees The verifier set you chose Varies with the set; a reason to know what it is
Protocol subscription None

What to take for a settlement design

Use the message layer, minimise the bridge. For a market whose collateral sits on several chains, the common first design is to make the collateral token omnichain — and the principle worth keeping is that settlement finality happens on exactly one chain, with everything else restricted to display and deposit paths. A message layer widens what you can reach; it does not widen where truth lives. And ATLAS's module boundary — risk separated from settlement — is worth copying independently of the product, because it is the split plumbing-skills-buyback argues most systems never make.

← All Dev Notes · Workspace Index · Top ↑

LayerZero — 기본 검증자는 아무도 적어두지 않은 신뢰 가정이다

LayerZero는 체인 간 임의 메시지를 옮기고, 검증자 집합을 애플리케이션이 직접 고르게 합니다. 그게 진짜 기능이자 진짜 함정입니다 — 고르지 않아도 고른 것이고, 지금 누구를 신뢰하는지 코드 어디에도 기록되지 않습니다.

30분, 테스트넷 두 곳. OApp 하나를 배포해 메시지 한 번 왕복시키고, lz:oapp:config:get 을 돌린 뒤 중요한 유일한 질문에 한 줄로 답합니다 — 나는 지금 누구를 신뢰하는가. 그 출력을 README 에 붙여 두세요. 그것이 신뢰 가정이고, 코드가 아니라 설정에 살기 때문입니다. 선택 3단계: ATLAS 가 공개한 4분할(매칭·청산·정산·리스크) 을 정산 설계 노트로 옮기기. 출처: layerzero.network, docs.layerzero.network. ATLAS 는 2026-08-26 발표, 2월에 낸 Zero L1 위에서 구동, 벤더 스트레스 테스트 기준 p50 서브밀리초·p99 2.641ms, 수수료 일부 ZRO 바이백·소각, 올가을 출시 예정, 협력사 Citadel Securities·DTCC·ARK Invest·ICE. 벤더 수치이고 미출시 제품 — 기대기 전에 확인할 것.

이 제품은 브릿지가 아니고, 브릿지로 읽으면 흥미로운 부분이 가려집니다. LayerZero는 메시지 레이어입니다 — 애플리케이션이 OApp 을 상속해 한 체인의 자기 컨트랙트에서 다른 체인의 자기 컨트랙트로 임의 페이로드를 보내고, 토큰 모양의 래퍼가 OFT·ONFT 입니다. 그 아래의 설계 선택은 검증이 모듈이라는 것입니다 — 프로토콜이 고정한 보안 가정이 아니라, 애플리케이션이 고르고 조합하는 DVN 집합.

그 모듈성은 진짜로 더 낫고, 동시에 결정을 조용히 당신에게 떠넘깁니다. 보안이 고정된 프로토콜은 신뢰 가정이 하나이고 좋든 나쁘든 모두가 물려받습니다. 검증을 고를 수 있는 프로토콜은 애플리케이션 수만큼의 가정을 갖고 — 한 번도 고르지 않은 애플리케이션은 그 선택을 피한 게 아니라 기본값을 받아들인 것입니다. 문제는 기본값이 나쁘다는 게 아닙니다. 기본값이 보이지 않는다는 것입니다 — 누가 당신의 메시지를 검증하는지 저장소 어디에도 적혀 있지 않으므로, 그 통합에서 가장 보안에 직결되는 사실이 모든 코드 리뷰에서 빠져 있습니다.

그래서 튜토리얼보다 실무 습관이 값집니다. 첫 배포 뒤 설정 조회를 돌리고 사람들이 읽는 자리에 출력을 붙이세요. 나는 지금 누구를 신뢰하는가매 순간 답이 존재하는 질문이고, 변수는 누군가 그것을 적어 뒀는가 뿐입니다. 의존성에 대해 같은 질문을 던지는 third-party-blast-radius, 그리고 하중을 받는 사실이 어떤 단일 파일 바깥에 있었던 storage-collision-admin-takeover 와 비교해 보세요.

두 번째 함정은 조용한 종류이고, 정확히 적어 둘 값이 있습니다. 발신자가 options 에 인코딩해 목적지 가스를 선지불합니다. 적게 주면 전송은 성공한 것처럼 보이는데 목적지에서 실행이 실패합니다 — 배달된 것처럼 보이지만 아무것도 하지 않은 메시지. 이 위에 올리는 프로덕션 경로는 필요해지기 전에 재시도 이야기가 쓰여 있어야 합니다. 호출 지점에서는 실패가 스스로를 알리지 않기 때문입니다.

그리고 전략적 메모는 다른 카드의 몫입니다. ATLAS는 LayerZero를 인프라에서 시장 인프라로 옮기고, 그러면 경쟁자가 바뀝니다 — Wormhole·Axelar 가 아니라 자기 거래소를 가진 체인들. 그 논지는 headless-exchange-engines 가 지고 갑니다. 여기 남는 것은 공학적 잔여물입니다 — ATLAS가 공개한 4분할(매칭·청산·정산·리스크)은 그대로 쓸 수 있는 모듈 경계이고, 리스크를 정산에서 분리한 것이 그 제품을 쓰든 안 쓰든 베낄 값이 있는 부분입니다.

동작 방식

첫 접촉, 그리고 중요한 세 줄

엔드포인트 주소, 목적지 EID, options 인코딩 — 나머지는 평범한 Solidity 입니다.

import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";

contract PingPong is OApp {
    using OptionsBuilder for bytes;
    string public lastMessage;

    constructor(address _endpoint, address _owner) OApp(_endpoint, _owner) {}

    function send(uint32 dstEid, string calldata text) external payable {
        bytes memory payload = abi.encode(text);
        // 목적지 가스를 발신 측이 정한다 — UX 의 핵심이자 첫 함정
        bytes memory options = OptionsBuilder.newOptions()
            .addExecutorLzReceiveOption(80_000, 0);
        _lzSend(dstEid, payload, options, MessagingFee(msg.value, 0), payable(msg.sender));
    }

    function _lzReceive(
        Origin calldata, bytes32, bytes calldata payload, address, bytes calldata
    ) internal override {
        lastMessage = abi.decode(payload, (string));
    }
}
npx hardhat lz:oapp:config:get     # 기본값을 읽는다 — 이것이 곧 신뢰 가정
npx hardhat lz:oapp:send --dst-eid 40161 --text "hello"

함정 둘, 그리고 왜 둘 다 조용한가

함정 어떻게 보이나 왜 아무도 못 잡나
목적지 가스 부족 전송은 성공, 목적지 실행은 실패 실패가 다른 체인에 있고, 호출 지점은 정상 반환
DVN 설정을 안 건드림 전부 잘 돌아감 저장소 어디에도 검증자 이름이 없어, 리뷰가 반대할 대상이 없음

둘은 같은 종류입니다하지 않음으로써 내려진 결정이고, 어디에도 기록되지 않습니다. 둘 다 고치는 습관의 비용은 명령 하나와 README 한 문단입니다.

비용, 그리고 어디서 흔들리나

항목 지불 대상 메모
발신 체인 가스 발신 체인 평범
목적지 실행 가스 발신 시 선지불 발신 시점에 견적 — 목적지가 혼잡하면 크게 흔들림
DVN 수수료 당신이 고른 검증자 집합 집합에 따라 다름. 그게 무엇인지 알아야 할 이유
프로토콜 구독료 없음

정산 설계로 가져갈 것

메시지 레이어는 쓰되 브릿지는 최소화한다. 담보가 여러 체인에 있는 마켓에서 흔한 첫 설계는 담보 토큰을 옴니체인화하는 것이고 — 지킬 원칙은 정산 확정이 정확히 한 체인에서만 일어나고, 나머지는 표시와 입금 경로로 제한하는 것입니다. 메시지 레이어는 닿을 수 있는 범위를 넓히지, 진실이 사는 곳을 넓히지 않습니다. 그리고 ATLAS 의 모듈 경계 — 리스크를 정산에서 분리 — 는 그 제품과 무관하게 베낄 값이 있습니다. plumbing-skills-buyback대부분의 시스템이 끝내 하지 않는다고 지적한 바로 그 분리이기 때문입니다.

← 전체 개발 노트 · 워크스페이스 인덱스 · 맨 위 ↑