Matrix logo

LayerX Forge Std Integration, Fixtures, and Solidity Test Support

This section captures the vendored Forge Standard Library surface that LayerX uses to write Solidity tests, plus the local test doubles and fixture files that exercise token beh...

Overview

This section captures the vendored Forge Standard Library surface that LayerX uses to write Solidity tests, plus the local test doubles and fixture files that exercise token behavior, wrapped native flows, router quoting, and reentrancy handling. The most important integration point is the root layerx/contracts/foundry.toml, which explicitly vendors forge-std under lib/ for tests only and keeps production src/ free of external imports.

The vendored copy under layerx/contracts/lib/forge-std/ provides the default Test harness, the standard IERC20 and IERC165 interfaces, helper documentation for storage inspection and cheatcodes, and the configuration files that support Forge’s own validation. The layerx/contracts/test/mocks/ directory then supplies the concrete mock contracts LayerX uses to simulate standard ERC-20 behavior, USDT-style approval rules, wrapped native token minting and withdrawal, router execution, and deliberate reentrancy attempts.

Forge Std Package and Repository Configuration

PathRoleConcrete behavior
layerx/contracts/foundry.tomlLayerX contracts Forge configSets src = "src", test = "test", script = "script", solc = "0.8.27", evm_version = "shanghai", optimizer runs at 200, and fs_permissions to read ./out. It also reads the paxeer RPC endpoint from ${PAXEER_RPC_URL}. A source comment states that forge-std is vendored under lib/ for tests only and is never imported by src/.
layerx/contracts/lib/forge-std/foundry.tomlVendored Forge Std configEnables fs_permissions with read-write access to ./, turns the optimizer on with optimizer_runs = 200, ignores error code 3860, and defines test RPC endpoints for mainnet, optimism_sepolia, arbitrum_one_sepolia, and needs_undefined_env_var. lint_on_build = false.
layerx/contracts/lib/forge-std/package.jsonPackage metadataDeclares the package name forge-std, version 1.16.1, description, homepage, bug tracker, license, author, publish surface src/**/*, and git repository metadata.
layerx/contracts/lib/forge-std/README.mdUsage guideDocuments install, helper contracts and libraries, storage slot discovery, cheatcode wrappers, TOML config loading, and logging guidance.
layerx/contracts/lib/forge-std/CONTRIBUTING.mdContributor guideDocuments code-of-conduct expectations, support channels, bug-report fields, PR workflow, build and test commands, cheatcode regeneration, review guidance, and release steps.

Package Metadata

The root layerx/contracts/foundry.toml explicitly treats forge-std as a vendored test-only dependency, which is the integration contract that keeps the test harness separate from production imports.

layerx/contracts/lib/forge-std/package.json identifies the vendored library as forge-std version 1.16.1 and publishes only src/**/*. The metadata points to the Forge Std guide for documentation, the Foundry issue tracker for bugs, and the upstream git repository for source history.

Contributor Workflow

layerx/contracts/lib/forge-std/CONTRIBUTING.md is a support file rather than runtime code, but it is part of the test-support surface because it explains how the vendored library is maintained.

TopicSource-backed guidance
Code of conductThe project follows the Rust Code of Conduct.
Help channelsFoundry Support Telegram, GitHub Discussions, and the Foundry Book.
Bug reportsInclude the Foundry version, platform, code snippets, and concrete reproduction steps.
Feature requestsProvide a detailed explanation and examples from other tools when relevant.
Pull requestsKeep commits logically grouped, fill out the PR template, and discuss updates constructively.
ValidationRun forge fmt --check and forge test -vvv.
Compiler compatibilityRun forge build --skip test --use solc:0.6.2, forge build --skip test --use solc:0.6.12, forge build --skip test --use solc:0.7.0, forge build --skip test --use solc:0.7.6, and forge build --skip test --use solc:0.8.0.
Cheatcode updatesRun ./scripts/vm.py to refresh src/Vm.sol after native cheatcode changes.
ReleasesUpdate relevant Cargo.toml versions, refresh documentation links, and perform a final breaking-change audit.
1. Format check | Run `forge fmt --check`.
2. Test suite | Run `forge test -vvv`.
3. Compiler matrix | Run `forge build --skip test --use solc:0.6.2`, `forge build --skip test --use solc:0.6.12`, `forge build --skip test --use solc:0.7.0`, `forge build --skip test --use solc:0.7.6`, and `forge build --skip test --use solc:0.8.0`.
4. Cheatcode regeneration | Run `./scripts/vm.py` when the native cheatcode surface changes.

Forge Std Helper Surfaces Documented in the README

layerx/contracts/lib/forge-std/README.md is the main usage guide for the vendored library. It describes the helper surfaces LayerX relies on in tests and scripts:

  • stdError supplies compiler built-in error selectors for expectRevert.
  • stdStorage wraps the record and accesses cheatcodes, can locate storage slots without knowing the full layout, supports mapping keys and struct field depth, and can write back through find() and checked_write().
  • stdCheats wraps prank, deal, hoax, startHoax, time manipulation, deployment helpers, and fuzzing helpers.
  • StdAssertions provides equality, inequality, comparison, approximate equality, and boolean assertions across primitive values and arrays.
  • StdConfig loads TOML data by chain identifier or alias and casts values into typed subtables.
  • console2.sol is the recommended logging surface because Forge traces decode it cleanly.
  • console.sol remains available for Hardhat compatibility, with a README note that uint256 and int256 logs are not decoded correctly in Forge traces.

UnpackedStruct

The README recommends console2.sol for decoded Forge traces and reserves console.sol for Hardhat compatibility.

layerx/contracts/lib/forge-std/README.md

This example struct appears in the storage walkthrough used to explain stdStorage. It is paired with the testFindStruct example, which resolves a and b by field depth and then validates the stored values with vm.load.

PropertyTypeDescription
auint256First field in the example unpacked struct.
buint256Second field in the example unpacked struct.
MethodDescriptionReturns
hiddenLoads a value from the hashed slot keccak256("my.random.var") using inline assembly.bytes32

Test Harness Contract

Test

layerx/contracts/lib/forge-std/src/Test.sol

Test is the default Forge Std testing base. It is declared as an abstract contract and combines TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, and StdUtils into a single test harness. The contract also imports logging, storage, JSON, math, TOML, and cheatcode modules so test files can use the standard Forge tooling surface from one import.

PropertyTypeDescription
IS_TESTboolPublic flag set to true for Forge’s test detection.

The contract declares no public methods of its own. Its role is to expose the inherited assertion, cheatcode, chain, invariant, and utility behavior through a single test entrypoint.

Helper Interfaces

IERC20

layerx/contracts/lib/forge-std/src/interfaces/IERC20.sol

IERC20 is the standard ERC-20 interface used by the test mocks and router adapter. The interface includes the standard token metadata, transfer, allowance, and approval methods, plus the standard Transfer and Approval events.

PropertyTypeDescription
none declaredInterface-only declaration.
EventDescription
TransferEmitted when tokens move from one account to another.
ApprovalEmitted when a spender allowance changes.
MethodDescription
totalSupplyReturns the number of tokens in existence.
balanceOfReturns the token balance for an account.
transferMoves tokens from the caller to a recipient.
allowanceReturns the remaining allowance for a spender.
approveSets the spender allowance for the caller’s tokens.
transferFromMoves tokens using allowance.
nameReturns the token name.
symbolReturns the token symbol.
decimalsReturns the token decimals.

IERC165

layerx/contracts/lib/forge-std/src/interfaces/IERC165.sol

IERC165 is the minimal ERC-165 surface used to query interface support.

PropertyTypeDescription
none declaredInterface-only declaration.
MethodDescription
supportsInterfaceQueries whether a contract supports a given interface identifier.

Test Mocks

layerx/contracts/test/mocks/ contains the Solidity doubles that the LayerX contract tests use to exercise token transfers, wrapped native value movement, router behavior, and reentrancy protection.

MockERC20

layerx/contracts/test/mocks/MockERC20.sol

MockERC20 is the standard, well-behaved ERC-20 test token. It implements IERC20, tracks balances and allowances in storage, emits the standard token events, and returns true from token-moving methods.

Constructor parameterTypeDescription
nstring memoryToken name used to initialize name.
sstring memoryToken symbol used to initialize symbol.
duint8Token decimals stored in _decimals.
PropertyTypeDescription
namestringPublic token name.
symbolstringPublic token symbol.
_decimalsuint8Immutable decimals value returned by decimals.
totalSupplyuint256Total minted supply.
balanceOfmapping(address => uint256)Per-account token balance.
allowancemapping(address => mapping(address => uint256))Per-owner, per-spender allowance table.
MethodDescriptionReturns
decimalsReturns _decimals.uint8
mintMints tokens to to, updates totalSupply, and emits Transfer from the zero address.none
transferDebits the caller, credits to, and emits Transfer.bool
approveSets the caller’s allowance for spender and emits Approval.bool
transferFromUses allowance unless it is type(uint256).max, then transfers tokens and emits Transfer.bool
EventDescription
TransferEmitted on minting and token transfers.
ApprovalEmitted when an allowance is set.

Mock PECOR Router

layerx/contracts/test/mocks/MockPECORRouter.sol

MockPECORRouter is a test DEX router. It pulls tokenIn from the caller, pays out USDL at a configured rate, and requires USDL liquidity to be pre-funded. It uses IPECORRouter and IERC20, with usdl stored as an immutable ERC-20 reference and rateE18 holding the per-token conversion rate.

Constructor parameterTypeDescription
usdl_addressAddress wrapped into the immutable usdl token reference.
PropertyTypeDescription
usdlIERC20Immutable USDL token used as the router payout asset.
rateE18mapping(address => uint256)Conversion rate table where output is scaled by 1e18.
MethodDescriptionReturns
setRateStores the output rate for a given input token.none
swapBestRouteRequires USDL as tokenOut, checks the deadline, pulls input tokens, calculates output via _out, enforces amountOutMin, and pays USDL to the caller.uint256 amountOut
getBestQuoteRequires USDL as tokenOut, computes the quote through _out, and sets best.amountOut and best.found.BestQuote memory best

The internal _out helper implements the conversion formula:

  • out(USDL base) = amountIn * rateE18[tokenIn] / 1e18

MockUSDT

layerx/contracts/test/mocks/MockUSDT.sol

MockUSDT models the non-standard USDT approval and transfer behavior used by the test suite to exercise SafeERC20 and force-approval paths. It intentionally does not implement IERC20 because the signatures differ from the standard interface.

PropertyTypeDescription
namestringToken name fixed to Tether USD.
symbolstringToken symbol fixed to USDT.
decimalsuint8Constant decimal count set to 6.
totalSupplyuint256Total minted supply.
balanceOfmapping(address => uint256)Per-account balance.
allowancemapping(address => mapping(address => uint256))Per-owner, per-spender allowance table.
MethodDescriptionReturns
mintMints tokens to to, updates totalSupply, and emits Transfer from the zero address.none
transferMoves tokens without returning a boolean value.none
approveRequires allowance to be reset to zero before a new non-zero approval and emits Approval.none
transferFromDeducts allowance unless it is type(uint256).max, then moves tokens without returning a boolean value.none
EventDescription
TransferEmitted on minting and token transfers.
ApprovalEmitted when allowance changes.

Mock Wrapped Native

layerx/contracts/test/mocks/MockWrappedNative.sol

MockWrappedNative is a minimal WETH-style wrapper used in tests. It inherits MockERC20 with the name Wrapped PAX, symbol WPAX9, and 18 decimals, and then adds native-value deposit and withdrawal behavior.

Constructor dependencyTypeDescription
MockERC20("Wrapped PAX", "WPAX9", 18)MockERC20Initializes the inherited ERC-20 state with wrapped-native token metadata.

The contract reuses the MockERC20 storage layout and adds no new storage variables.

MethodDescriptionReturns
depositAccepts native value, credits the caller’s wrapped balance, increases totalSupply, and emits Transfer from the zero address.none
withdrawDebits wrapped balance and totalSupply, sends native value back to the caller, requires the transfer to succeed, and emits Transfer to the zero address.none

Reentrant Token

layerx/contracts/test/mocks/ReentrantToken.sol

ReentrantToken is the malicious token used to prove that value-moving entrypoints are protected by nonReentrant. It inherits MockERC20, stores a target payload, and attempts to call back into the target during transferFrom when armed.

Constructor dependencyTypeDescription
MockERC20("Reentrant", "RE", 6)MockERC20Initializes the inherited ERC-20 metadata for the malicious token.
PropertyTypeDescription
targetaddressCall target used for the reentry attempt.
payloadbytesCalldata sent to the target during the reentry attempt.
armedboolSingle-shot guard that enables the callback attempt.
reentryAttemptedboolRecords whether a callback was attempted.
reentrySucceededboolRecords whether the callback returned success.
MethodDescriptionReturns
armStores target_ and payload_, then enables the one-shot reentry attempt.none
transferFromWhen armed, clears the arm flag, records the attempt, calls target.call(payload), stores the success flag, and then continues with super.transferFrom.bool

Fixture Files

The fixture set under layerx/contracts/lib/forge-std/test/fixtures/ provides the sample inputs and outputs used by the vendored Forge Std tests.

PathShapePurpose
layerx/contracts/lib/forge-std/test/fixtures/test.jsona, b, and nested object c with matching a and b fieldsDemonstrates JSON fixture parsing with scalar and nested data.
layerx/contracts/lib/forge-std/test/fixtures/test.tomla, b, and nested table [c] with matching a and b fieldsMirrors the JSON fixture in TOML form for parser parity.
layerx/contracts/lib/forge-std/test/fixtures/config.tomlChain-scoped config with mainnet and optimism sections, typed subtables, arrays, and env-var-backed RPC URLsExercises StdConfig style loading across bool, address, uint, int, bytes32, bytes, and string fields.
layerx/contracts/lib/forge-std/test/fixtures/broadcast.log.jsonForge broadcast log with transactions, receipts, libraries, pending, path, returns, and timestampCaptures a full broadcast record for transaction and receipt parsing.

config.toml

The fixture config uses two example environments, mainnet and optimism, and assigns values by type-specific subtables. It includes boolean arrays, address arrays, signed and unsigned integers, bytes32 arrays, raw bytes arrays, string arrays, and RPC URL placeholders driven by environment variables.

broadcast.log.json

The broadcast log fixture stores a complete run record with call transactions, deployment receipts, linked library addresses, a pending list, the broadcast path, return values, and a timestamp. The transaction samples include calls against Test contract functions such as multiple_arguments, inc, and t, which makes the file useful for broadcast parsing and trace validation.

Test Execution Flow

This flow mirrors the way the README examples and the mock contracts are meant to be used together: a Solidity test inherits Test, sets up token state with mocks, and then verifies results with Forge cheatcode-backed assertions and storage reads.