Skip to main content
ClaudeWave
Skill55 estrellas del repoactualizado 4mo ago

LayerZero Integration Patterns

>

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/PurpleAILAB/Vigilo /tmp/layerzero-integration-patterns && cp -r /tmp/layerzero-integration-patterns/packages/claude/skills/integration-patterns/layerzero ~/.claude/skills/layerzero-integration-patterns
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# 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**