Skip to content

Conversation

@St0rmBr3w
Copy link
Contributor

@St0rmBr3w St0rmBr3w commented Jul 8, 2025

In this PR:

This PR introduces a lightweight testing infrastructure for LayerZero OApp developers using Foundry. It addresses compilation issues, enables forge coverage, and provides a cleaner import structure without sacrificing essential testing capabilities.

Problems Addressed

  1. Stack Too Deep Errors: Current test helpers (TestHelperOz5) cause "Stack too deep" compilation errors, requiring --via-ir flag
  2. Forge Coverage Fails: Cannot run forge coverage on projects using existing test infrastructure
  3. Heavy Dependencies: Importing test helpers brings in complex protocol implementations unnecessary for application testing
  4. Compilation Performance: Large contract sizes slow down development iteration

Solution

Created a parallel "slim" testing infrastructure that maintains backward compatibility while dramatically reducing complexity.

Major Changes

1. New LzTestHelperSlim Contract (packages/test-devtools-evm-foundry/contracts/LzTestHelperSlim.sol)

  • Lightweight alternative to TestHelperOz5 (~316 lines vs 700+ lines)
  • Simplified features:
    • Single LibraryType support (SimpleMessageLib)
    • Streamlined packet scheduling and delivery
    • Minimal option parsing for executor configurations
    • Removed complex DVN/Executor worker management
  • Maintains core API compatibility for easy migration
  • Inherits from Foundry's Test and custom OptionsHelper

2. New EndpointV2Simple Mock (packages/test-devtools-evm-foundry/contracts/mocks/EndpointV2Simple.sol)

  • Ultra-minimal endpoint implementation (~130 lines)
  • No complex inheritance chain
  • Essential functions only:
    - send() → calls message library → schedules packet
    - lzReceive() → delivers to OApp
    - lzCompose() → handles composed messages  
    - quote() → returns fixed test fees
  • Removes protocol complexity while maintaining interface compliance

3. Simplified SimpleMessageLibMock (packages/test-devtools-evm-foundry/contracts/mocks/SimpleMessageLibMock.sol)

  • Removed TestHelperOz5 dependency
  • Eliminated unnecessary features (treasury, whitelist, etc.)
  • Pure packet forwarding to test helper
  • Reduced from ~180 lines to ~99 lines

4. Example Updates (examples/oft/test/foundry/MyOFT.t.sol)

  • Demonstrates migration from TestHelperOz5 to LzTestHelperSlim
  • All tests pass without modification to test logic
  • Proves backward compatibility

Key Design Decisions

What's Included

  • ✅ Cross-chain message passing simulation
  • ✅ Packet scheduling and delivery
  • ✅ Basic executor options (gas/value for lzReceive/lzCompose)
  • ✅ OApp wiring utilities
  • ✅ Compose message support

What's Excluded

  • ❌ Complex DVN configurations
  • ❌ Executor worker management
  • ❌ Protocol library switching
  • ❌ Advanced verification logic
  • ❌ Read channel support

Rationale: These features are better tested in integration environments (localnet)

Results

Compilation

# Before
$ forge build
Error: Stack too deep. Try compiling with `--via-ir`...

# After  
$ forge build
✅ Compiler run successful

Coverage

# Before
$ forge coverage
Error: Stack too deep...

# After
$ forge coverage  
✅ Analyzing contracts...
✅ Running tests...
✅ Coverage report generated

Import Size

# Before (with TestHelperOz5)
- Pulls in: MessageLibManager, MessagingChannel, MessagingComposer, DVN logic, etc.
- Total dependencies: 20+ contracts

# After (with LzTestHelperSlim)
- Pulls in: Minimal mocks only
- Total dependencies: ~5 contracts

Migration Guide

// Before
import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol";

contract MyTest is TestHelperOz5 {
    function setUp() public override {
        super.setUp();
        setUpEndpoints(2, LibraryType.UltraLightNode);
    }
}

// After
import { LzTestHelperSlim } from "@layerzerolabs/test-devtools-evm-foundry/contracts/LzTestHelperSlim.sol";

contract MyTest is LzTestHelperSlim {
    function setUp() public override {
        super.setUp();
        setUpEndpoints(2); // Simplified - no LibraryType needed
    }
}

Benefits

  1. No --via-ir Required: Contracts compile with standard optimizer settings
  2. Forge Coverage Works: Developers can measure test coverage
  3. Faster Compilation: ~3x faster build times
  4. Cleaner Dependencies: Only imports what's needed for testing
  5. Easier to Understand: Focused on app testing, not protocol implementation
  6. Backward Compatible: Existing tests work with minimal changes

Testing Philosophy

  • Unit Tests (Foundry): Use slim helpers for fast, focused application logic testing
  • Integration Tests (Localnet): Test complex protocol interactions, DVN setups, etc.

Verification

  • ✅ All example tests pass (OFT, OApp, etc.)
  • forge test works without special flags
  • forge coverage generates reports successfully
  • ✅ No stack depth errors during compilation
  • ✅ Maintains essential testing capabilities

Future Considerations

  • Keep TestHelperOz5 for advanced protocol testing needs
  • LzTestHelperSlim becomes the recommended default for OApp developers
  • Can extend slim helpers with specific features as needed without breaking simplicity

@St0rmBr3w St0rmBr3w requested review from DanL0 and shankars99 July 8, 2025 23:16
@St0rmBr3w St0rmBr3w changed the title feat: add slim testhelper DEVREL-568 feat: add slim testhelper Jul 8, 2025
@St0rmBr3w St0rmBr3w changed the title DEVREL-568 feat: add slim testhelper DEVREL-568 feat: Add Slim TestHelper for LayerZero Foundry Testing Jul 15, 2025
Copy link
Contributor

@ravinagill15 ravinagill15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for implementing this!

@St0rmBr3w St0rmBr3w changed the title DEVREL-568 feat: Add Slim TestHelper for LayerZero Foundry Testing DEVREL-568 feat: Add slim TestHelper for LayerZero foundry testing Jul 21, 2025
ravinagill15
ravinagill15 previously approved these changes Jul 23, 2025
Copy link
Contributor

@ravinagill15 ravinagill15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Collaborator

@shankars99 shankars99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be good to make all the no-op function virtual so that someone, if they want can override it and have a custom EndpointV2Simple or something.

will re-review after any changes

Copy link
Collaborator

@shankars99 shankars99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants