Matrix logo

LayerX Forge Std Integration, Test Mocks, and Solidity Test Support

Vendored Forge Standard Library, test mock contracts (MockERC20, MockUSDT, MockWrappedNative, MockPECORRouter, ReentrantToken), and Solidity test fixtures for the LayerX contract suite.

Overview

The LayerX contract test suite uses vendored forge-std (v1.16.1) under lib/ for tests only. Production src/ has zero external imports. The test/mocks/ directory provides concrete mock contracts to simulate ERC-20 behavior, USDT-style approval rules, wrapped native flows, router execution, and reentrancy attacks.

Forge Std Configuration

Source: layerx/contracts/foundry.toml

KeyValueEffect
libs["lib"]Resolves forge-std from lib/
fs_permissionsread ./outAllows test file reads

The vendored forge-std package.json declares version 1.16.1.

Test Harness

forge-std/src/Test.sol is the abstract base contract combining TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, and StdUtils. LayerX tests inherit from Test to access:

  • vm.deal / vm.prank / vm.startPrank for address impersonation
  • vm.expectRevert with stdError selectors
  • assertEq / assertTrue / assertGt for assertions
  • vm.load for direct storage reads
  • console2.log for decoded Forge trace logging

Test Mock Contracts

MockERC20

Source: layerx/contracts/test/mocks/MockERC20.sol

Standard, well-behaved ERC-20 test token.

ConstructorTypeDescription
nstringToken name
sstringToken symbol
duint8Decimals

Methods: mint(to, amount), transfer, approve, transferFrom (unlimited allowance when type(uint256).max).

MockUSDT

Source: layerx/contracts/test/mocks/MockUSDT.sol

Models non-standard USDT behavior:

  • transfer and transferFrom return void (no boolean)
  • approve requires resetting allowance to zero before setting a new non-zero value

Used to exercise SafeERC20.forceApprove and the no-boolean-return wrapper.

MockWrappedNative

Source: layerx/contracts/test/mocks/MockWrappedNative.sol

WETH-style wrapper inheriting MockERC20 ("Wrapped PAX", "WPAX9", 18 decimals). Methods: deposit() (accepts native value), withdraw(amount) (sends native value back).

MockPECORRouter

Source: layerx/contracts/test/mocks/MockPECORRouter.sol

Test DEX router for swap-based deposits.

PropertyTypeDescription
usdlIERC20Immutable USDL payout asset
rateE18mapping(address => uint256)Per-token conversion rate (scaled by 1e18)

Methods:

  • setRate(tokenIn, rate) - set conversion rate
  • swapBestRoute(tokenIn, tokenOut, amountIn, amountOutMin, deadline) - execute swap (requires USDL as tokenOut)
  • getBestQuote(tokenIn, tokenOut, amountIn) - read-only quote

Formula: out = amountIn * rateE18[tokenIn] / 1e18

ReentrantToken

Source: layerx/contracts/test/mocks/ReentrantToken.sol

Malicious token that attempts reentry during transferFrom. Inherits MockERC20 ("Reentrant", "RE", 6 decimals).

PropertyTypeDescription
targetaddressCall target for reentry
payloadbytesCalldata for reentry
armedboolSingle-shot guard
reentryAttemptedboolWhether callback was attempted
reentrySucceededboolWhether callback succeeded

Methods:

  • arm(target, payload) - enable one-shot reentry attempt
  • transferFrom - when armed, clears arm, records attempt, calls target.call(payload), then continues with normal transfer

Used to prove that vault entrypoints are protected by nonReentrant.

Solidity Test Files

SettlementAnchor.t.sol

Tests: writer can anchor and root is visible via rootOf; non-writers rejected; same batch id cannot be recorded twice; zero roots rejected; governor can rotate writer.

SafeERC20.t.sol

Tests with a harness contract exposing library functions: standard transfers succeed; USDT-style no-boolean tokens accepted; forceApprove handles reset-to-zero; calling into non-contract address reverts.

LayerXVault.t.sol

Tests: direct USDL deposits mint 1:1; swap deposits enforce slippage/deadline; native deposits wrap and swap; settlement is idempotent/capped/reserve-bounded; force-exit covers initiate/challenge/finalize with epoch checks; pause/unpause obey access rules; governance is two-step; reentrancy guard blocks malicious tokens; exit-delay bounds enforced.

PaymentChannel.t.sol (Deus)

Tests: fund and payout, close and refund, availableWei accounting.

Fixture Files

FilePurpose
lib/forge-std/test/fixtures/test.jsonJSON fixture with scalar + nested data
lib/forge-std/test/fixtures/test.tomlTOML mirror of JSON fixture
lib/forge-std/test/fixtures/config.tomlChain-scoped config with typed subtables
lib/forge-std/test/fixtures/broadcast.log.jsonFull broadcast record for parsing tests

Test Execution Pattern

1. Developer writes Solidity test inheriting Test
2. Test deploys mock contracts (MockERC20, MockUSDT, MockWrappedNative, MockPECORRouter, ReentrantToken)
3. Test calls vault/anchor methods with controlled mock state
4. Test asserts with assertEq / vm.expectRevert / vm.load
5. forge test --match-path test/ContractName.t.sol