Skip to main content

layerzero-integration-patterns

Auto-loaded by cross-chain-auditor agent during Phase 2 when LayerZero is detected. Provides patterns for: OApp security (peer validation), OFT tokens (slippage), compose message validation, gas options. Critical: missing peer check, wrong peer encoding, no compose validation, insufficient executor gas.

설치로 이동

소스 정보

저장소
BitterSecurity/Vigilo
최근 소스 활동
2026년 1월 26일 12:30
감지된 SKILL.md 언어
영어
스타
66
포크
18

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
LayerZero Integration Patterns
description
Auto-loaded by cross-chain-auditor agent during Phase 2 when LayerZero is detected. Provides patterns for: OApp security (peer validation), OFT tokens (slippage), compose message validation, gas options. Critical: missing peer check, wrong peer encoding, no compose validation, insufficient executor gas.
user-invocable
false
# LayerZero Integration Patterns This skill provides comprehensive knowledge for auditing LayerZero integrations. ## LayerZero V2 Architecture | Component | Purpose | |-----------|---------| | Endpoint | Entry point for sending/receiving | | OApp | Omnichain Application base | | OFT | Omnichain Fungible Token | | DVN | Decentralized Verifier Network | | Executor | Message delivery | --- ## OApp Security Patterns ### Standard Receiver Implementation ```solidity import { OApp, Origin } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol"; contract MyOApp is OApp { constructor( address _endpoint, address _delegate ) OApp(_endpoint, _delegate) {} function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal override { // CRITICAL: Validate source chain require( peers[_origin.srcEid] != bytes32(0), "Peer not set" ); // CRITICAL: Validate source address require( _origin.sender == peers[_origin.srcEid], "Invalid sender" ); // Process message _processMessage(_message); } } ``` ### Required Security Checks | Check | Location | Risk if Missing | |-------|----------|-----------------| | Peer validation | `_lzReceive` | Accept forged messages | | Chain validation | `_lzReceive` | Cross-chain injection | | GUID uniqueness | Optional | Replay attacks | | Compose validation | `_lzCompose` | Malicious compose calls | --- ## OFT (Omnichain Fungible Token) Security ### Standard OFT Pattern ```solidity import { OFT } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol"; contract MyOFT is OFT { constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _delegate ) OFT(_name, _symbol, _lzEndpoint, _delegate) {} // Verify amount received function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal override returns (uint256 amountSentLD, uint256 amountReceivedLD) { // Standard debit with slippage protection (amountSentLD, amountReceivedLD) = super._debit( _from, _amountLD, _minAmountLD, _dstEid ); // Custom validation if needed require(amountReceivedLD >= _minAmountLD, "Slippage exceeded"); } } ``` ### OFT Vulnerabilities **1. Missing Slippage Protection** ```solidity // DANGEROUS: No minimum amount check function send( uint32 _dstEid, bytes32 _to, uint256 _amountLD, bytes calldata _options ) external payable { // No minAmountLD protection! _send(_dstEid, _to, _amountLD, _options); } // SECURE: Include minimum function send( uint32 _dstEid, bytes32 _to, uint256 _amountLD, uint256 _minAmountLD, // Add this! bytes calldata _options ) external payable { require(_minAmountLD > 0, "Set minimum"); _send(_dstEid, _to, _amountLD, _minAmountLD, _options); } ``` **2. Decimal Conversion Issues** ```solidity // LayerZero uses shared decimals (usually 6) // Local token might have 18 decimals // DANGEROUS: Precision loss on small amounts uint256 sharedDecimals = 6; uint256 localDecimals = 18; uint256 decimalConversionRate = 10 ** (localDecimals - sharedDecimals); // Amount like 0.000001 tokens becomes 0 in shared format! ``` --- ## Peer Configuration Security ### Trusted Peer Setup ```solidity // Only owner can set peers function setPeer( uint32 _eid, bytes32 _peer ) public override onlyOwner { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } // Peer format: bytes32(uint256(uint160(address))) // Ensure address is padded correctly! ``` ### Peer Validation Vulnerabilities **1. Missing Peer Check** ```solidity // DANGEROUS: Accepts from anyone function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal override { // Missing peer validation! _process(_message); } ``` **2. Incorrect Peer Encoding** ```solidity // DANGEROUS: Wrong encoding bytes32 peer = bytes32(abi.encodePacked(remoteAddress)); // Wrong! // CORRECT: Proper padding bytes32 peer = bytes32(uint256(uint160(remoteAddress))); ``` --- ## Compose Message Security ### Compose Pattern ```solidity import { OAppComposer } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppComposer.sol"; contract MyComposer is OAppComposer { function _lzCompose( address _oApp, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal override { // CRITICAL: Validate compose source require(_oApp == trustedOApp, "Invalid OApp"); // Process composed message _handleCompose(_message); } } ``` ### Compose Vulnerabilities **1. Missing OApp Validation** ```solidity // DANGEROUS: Accepts compose from any OApp function _lzCompose( address _oApp, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal override { // No _oApp validation! _processCompose(_message); } ``` --- ## Gas & Options Security ### Options Encoding ```solidity import { OptionsBuilder } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol"; using OptionsBuilder for bytes; // Build options with sufficient gas bytes memory options = OptionsBuilder .newOptions() .addExecutorLzReceiveOption(200000, 0) // Gas limit .addExecutorNativeDropOption(1 ether, receiver); // Native drop // Send with options endpoint.send{value: fee}( dstEid, message, options, MessagingFee(fee, 0), payable(msg.sender) ); ``` ### Gas Vulnerabilities **1. Insufficient Executor Gas** ```solidity // DANGEROUS: May fail on destination bytes memory options = OptionsBuilder .newOptions() .addExecutorLzReceiveOption(50000, 0); // Too low! // RECOMMENDED: Calculate based on callback complexity uint128 gasForCallback = 200000; // Sufficient for your _lzReceive ``` --- ## LayerZero Audit Checklist ### OApp Security - [ ] Peer validation in `_lzReceive` - [ ] Source chain (srcEid) validated - [ ] Source sender validated against peer - [ ] GUID tracked if replay protection needed - [ ] Compose source validated in `_lzCompose` ### OFT Security - [ ] Slippage protection implemented - [ ] Decimal conversion correct - [ ] Minimum amounts enforced - [ ] Shared decimals configured correctly ### Configuration - [ ] Peers set correctly (proper encoding) - [ ] DVN/Executor configured appropriately - [ ] Fee estimation correct - [ ] Gas limits sufficient ### Edge Cases - [ ] Message failure handling - [ ] Stuck message recovery - [ ] Admin key security for peer updates - [ ] Rate limiting if needed ## Common Vulnerabilities Summary | Vulnerability | Impact | Detection | |--------------|--------|-----------| | Missing peer validation | Message forgery | No `peers[srcEid]` check | | Wrong peer encoding | Silent failures | `abi.encodePacked` instead of padding | | No compose validation | Compose injection | No `_oApp` check in `_lzCompose` | | Insufficient gas | Failed messages | Low gas in options | | No slippage protection | Value loss | No `minAmountLD` |
GitHub에서 보기