Hook
Đầu tháng 5, một smart contract auditor mà tôi quen gửi cho tôi một đoạn code nhỏ. Anh ấy nói: "Mày nhìn cái này đi, tìm lỗi dùm tao." Nhìn qua, tôi thấy một hàm withdraw với access control trong suốt. Hàm này có thể gọi bởi bất kỳ ai, miễn là họ pass một chữ ký EIP-712 từ một địa chỉ nhất định. Cổ điển. Nhưng khi debug sâu vào, tôi nhận ra chữ ký đó không hề liên quan đến nội dung của hàm — nó chỉ là một chữ ký giả định, như kiểu "tôi đồng ý cho phép withdraw." Không có bất kỳ ràng buộc nào với số lượng token, destination chain, hay thậm chí là ID của transaction.
Đây là LayerZero. Và câu chuyện về lỗ hổng này sẽ thay đổi cách nhìn của bạn về "chiếc cầu nối" đang được hàng trăm dự án tin dùng.
Context
LayerZero, với tư cách là một omnichain interoperability protocol, đã trở thành một trong những narrative mạnh nhất trong chu kỳ này. Nó không chỉ là một cross-chain bridge thông thường. Nó là một messaging layer: cho phép các smart contract trên các blockchain khác nhau gửi và nhận message (gói dữ liệu) qua một mạng lưới các node được gọi là "Ultra Light Node" (ULN).
Thay vì dựa vào một bridge tập trung hay một validator set chung, LayerZero tách rời quá trình xác thực giao dịch thành hai party: Oracle (bên cung cấp block header) và Relayer (bên chuyển proof). Cả hai phải collude để gian lận được. Đây là cơ chế bảo mật được quảng bá rầm rộ.
Nhưng vấn đề nằm ở implementation. Các dự án xây dựng trên LayerZero không phải lúc nào cũng implement đúng spec. Đặc biệt, khi nói đến thành phần "OApp" (Omnichain Application) — nơi developer tự xử lý logic gửi và nhận message.

Core
Bây giờ, hãy nhìn vào phát hiện của auditor kia.
Có một hàm trong OApp sample code được mở ra cho public call. Hàm này, với tên gọi mơ hồ là lzReceive, được thiết kế để endpoint của LayerZero gọi khi message đến. Nhưng trong code mẫu, không có bất kỳ access control nào. Không có check xem người gọi có phải là LayerZero Endpoint chính thống hay không.
Ai cũng có thể gọi lzReceive trực tiếp, với bất kỳ payload nào.
Điều này có nghĩa là: bất kỳ ai cũng có thể gửi một message giả đến OApp của bạn — giả như đến từ một chain khác — và OApp sẽ tin tưởng xử lý nó. Ví dụ: một message giả bảo "hãy mint 1000 token cho địa chỉ A." Nếu OApp không có check thêm, nó sẽ mint.
Đây là lỗi "unauthenticated message delivery". Lỗi này không nằm ở LayerZero core, mà nằm ở cách developer implement OApp.
Nhưng đó mới chỉ là phần nổi.
Đi sâu hơn: lzReceive thường được dùng để nhận message từ chain khác. Message đó được đóng gói với _origin (src chain ID, sender address). Nếu kẻ tấn công gọi trực tiếp lzReceive với _origin giả mạo, họ có thể giả mạo bất kỳ sender nào.
Có ba biến thể phổ biến của lỗ hổng này:
- Không check origin sender — Ai cũng có thể gửi message.
- Check origin sender nhưng không check source chain — Có thể giả mạo từ chain khác.
- Check cả hai, nhưng dùng mapping sai — Developer lưu
trustedRemotebằngkeccak256(abi.encode(chainId, address)), một typo nhỏ trong encode cũng phá hỏng toàn bộ.
Trong audit thực tế, tôi từng thấy một dự án lưu trustedRemote cho mỗi cặp chain-sender, nhưng không bao gồm chain ID của remote. Kết quả: kẻ tấn công deploy hợp đồng giả trên chain khác, với address trùng (deterministic deployment), và tấn công thành công.
Contrarian Angle
Đây là điểm đau: LayerZero càng phổ biến, càng có nhiều developer non-chuyên nghiệp xây dựng OApp. Và mỗi OApp lỏng lẻo là một lỗ hổng tiềm tàng.
Nhưng điều ngược đời là: cộng đồng và thị trường đang coi LayerZero như một giải pháp hoàn chỉnh. Các dự án huy động hàng trăm triệu USD với narrative "LayerZero-secured cross-chain".
Thực tế: LayerZero chỉ cung cấp transport layer. Security layer là do developer tự build. LayerZero biết điều này, họ có documentation rất dài về cách implement an toàn. Nhưng khi code được fork trên GitHub, phần documentation thường bị bỏ qua.
Câu chuyện này giống hệt những ngày đầu của Uniswap: Uniswap V2 (Vyper) có lỗ hổng reentrancy ở addLiquidity nếu token không chuẩn ERC20. Hàng trăm fork bị drain. Uniswap không sai, nhưng người dùng vẫn mất tiền.

LayerZero đang ở vị trí tương tự: nó là victim của thành công của chính nó. Càng nhiều người dùng, càng nhiều code lỏng lẻo, càng nhiều lỗ hổng.
Takeaway
Tôi tin rằng trong 12-18 tháng tới, chúng ta sẽ thấy một vụ hack cross-chain lớn (trên 50 triệu USD) mà lỗ hổng nằm hoàn toàn ở implementation của OApp, chứ không phải LayerZero core. Khi đó, câu hỏi sẽ không phải "LayerZero có an toàn không?" mà là "Bạn có thực sự hiểu code bạn đang fork không?" Với cơn sốt airdrop và điểm số sắp tới, câu trả lời có lẽ là "không".