> ## Documentation Index
> Fetch the complete documentation index at: https://docs.railnet.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Vehicle implementations

> Validate a Vehicle adapter against the STEAM conformance suite using Railnet's Foundry test harness

<Info>This page covers the smart contract implementation details. See [Glossary](/developers/glossary).</Info>

Railnet ships a Foundry-based test harness that exposes **100+ STEAM conformance tests** through a single base contract. Inherit from it to validate your Vehicle against the full state machine and lifecycle specification.

## Prerequisites

* [Foundry](https://book.getfoundry.sh/) installed and available on `PATH`
* A Vehicle contract implementing `IVehicle`
* Working knowledge of the [STEAM standard](/developers/contracts/steam-standard)

## Create the base test contract

Place the test file at `test/vehicles/<your_vehicle>/<YourVehicle>Vehicle.t.sol` and inherit from `STEAMSingleAssetTester` to activate the conformance suite.

<CodeGroup>
  ```solidity Solidity theme={null}
  import {STEAMSingleAssetTester} from "test/test_utils/STEAM.SingleAsset.t.sol";
  import {MyVehicle} from "src/vehicles/my_vehicle/MyVehicle.sol";

  contract MyVehicleTest is STEAMSingleAssetTester {
      function setUp() external virtual {
          // 1. Deploy dependencies (mocks, assets)
          $asset = IERC20Metadata(address(new MockAsset()));

          // 2. Deploy your Vehicle
          ($vehicle,) = _deployMyVehicle(
              _deployCoreFactory(),
              MyVehicleFactory.SpawnParams({
                  asset: address($asset),
                  accessControl: _get_access_control(),
                  feeManager: _get_fee_manager(),
                  modulesManager: _get_modules_manager(),
                  // ... other params
              })
          );
      }
  }
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

## Configure the test environment

The base tester exposes internal hooks for optional components. Each defaults to `address(0)`; override the ones your Vehicle depends on.

<CodeGroup>
  ```solidity Solidity theme={null}
  function _get_access_control() internal virtual returns (ExternalAccessControl) {
      return ExternalAccessControl(address(0));
  }

  function _get_fee_manager() internal virtual returns (FeeManager) {
      return FeeManager(address(0));
  }

  function _get_modules_manager() internal virtual returns (ModulesManager) {
      return ModulesManager(address(0));
  }
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

## Add vehicle-specific tests

`STEAMSingleAssetTester` covers the generic state machine. Extend it with tests that exercise your adapter's protocol-specific logic — constructor guards, custom `data` field parsing, protocol edge cases.

<CodeGroup>
  ```solidity Solidity theme={null}
  function test_initialize_wrong_market_decimals() external {
      // Custom logic to verify vehicle-specific initialization
  }

  function test_deposit_with_custom_data() external {
      // Test protocol-specific data field handling
  }
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

## Test composition pattern

Exercise the Vehicle under each supported configuration by creating variant test files that extend the base contract and override the component hooks.

<Steps>
  <Step title="Baseline (no optional components)">
    `MyVehicle.t.sol` — the base file defined above. All hooks resolve to `address(0)`.
  </Step>

  <Step title="With FeeManager">
    Create `MyVehicle.WithFeeManager.t.sol`:

    <CodeGroup>
      ```solidity Solidity theme={null}
      import {MyVehicleTest} from "./MyVehicle.t.sol";

      contract MyVehicleWithFeeManagerTest is MyVehicleTest {
          function _get_fee_manager() internal override returns (FeeManager) {
              return _deployFeeManager(/* params */);
          }
      }
      ```

      ```typescript TypeScript theme={null}
      // Coming soon
      ```
    </CodeGroup>
  </Step>

  <Step title="With ModulesManager">
    Create `MyVehicle.WithModulesManager.t.sol` and override `_get_modules_manager()`.
  </Step>

  <Step title="With AccessControl">
    Create `MyVehicle.WithAccessControl.t.sol` and override `_get_access_control()`.
  </Step>
</Steps>

## Key helper methods

`STEAMSingleAssetTester` exposes the following internal helpers for use in custom test cases:

| Helper                                                       | Description                                                                         |
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `_get_and_prepare_query(user, receiver, mode, amount, salt)` | Mints and approves the input asset, then returns a fully-formed `Query` struct      |
| `_get_run_config(query)`                                     | Builds a `RunConfig` used to drive the query through the STEAM state machine        |
| `_compute_amount(uint256)`                                   | Clamps a fuzzed value to a bounded range (1–1000 units)                             |
| `_unit(count)`                                               | Scales an integer count by the asset's decimals (e.g., `_unit(1) == 1e18` for WETH) |

## Inherited test categories

Inheriting from `STEAMSingleAssetTester` activates coverage across the following areas:

* **State machine** — valid and invalid transitions across every STEAM state
* **Input validation** — zero amounts, unsupported assets, invalid receivers
* **Access control** — enforcement of caller permissions on lifecycle methods
* **Fee handling** — correct accrual and settlement of deposit and redeem fees
* **Module execution** — interaction with protocol modules through `ModulesManager`

## Running tests

```bash theme={null}
# Execute the full test suite for the Vehicle
forge test --match-contract MyVehicle

# Increase verbosity to surface traces and revert reasons
forge test --match-contract MyVehicle -vvv

# Target a single test case
forge test --match-test test_initialize_wrong_market_decimals -vvv
```
