Skip to main content
This page covers the smart contract implementation details. See Glossary.
Modules are external contracts that extend your Multi-Vehicle’s capabilities — for example, distributing Merkl rewards or integrating custom logic. The Modules Manager provides a secure, timelock-protected registry for adding, updating, and executing modules. As an asset manager, you typically execute modules that have been registered and approved. If you are operating a platform-owned Multi-Vehicle, the platform owner manages the module registry — you can execute authorized modules using the EXEC role.

How modules work

The Modules Manager acts as both a registry and an execution gateway:
  1. Registry — Stores authorized module addresses mapped to unique bytes32 identifiers
  2. Execution gateway — Authorized callers trigger module execution on target contracts (vehicles)
  3. Target protection — Each target contract must explicitly allow a module before it can be executed on it
  4. Security — Adding or updating modules is protected by a mandatory timelock

Module lifecycle

Every module goes through a three-step process:
  1. Registration — An authorized MODULE_MANAGER calls addModule. This creates a pending request and starts the timelock countdown.
  2. Finalization — After the timelock elapses, anyone can call approvePendingModule to activate the module.
  3. Authorization — The target contract (e.g. a Vehicle) calls allowModule to permit execution of that module on itself.
The timelock is a mandatory delay between requesting a module addition and its activation. This gives stakeholders time to review the proposed module before it becomes executable.

Prerequisites

You need the following roles on your External Access Control, scoped to the Modules Manager contract:

Add a module

Adding a module is a two-step process separated by the timelock.
1

Request module addition

Call addModule with the module’s unique ID and its contract address. The ID must match the value returned by IModule(module).MODULE_ID().Requires: MODULE_MANAGER role.
2

Wait for the timelock

Check the current timelock duration and wait for it to elapse.
3

Approve the pending module

After the timelock has passed, finalize the module registration. This function can be called by any account.
4

Allow the module on target contracts

Each target contract must explicitly authorize the module before it can be executed. For Vehicles, use the wrapper function that calls allowModule on the Modules Manager.Requires: VEHICLE_ALLOW role scoped to the Vehicle.

Execute a module

Once a module is active in the registry and allowed on the target, you can execute it. Requires: EXEC role.
The target contract must implement the IModuleTarget interface. All Railnet vehicles implement this interface by default.

Update a module

To update a module’s implementation address, the process mirrors addition — request, timelock, approve.
Updating a module does not require re-allowing it on target contracts. Existing allowModule authorizations carry over to the new implementation.

Remove a module

Removing a module revokes its authorization across all target contracts immediately. Requires: MODULE_MANAGER role.
Removal fails if there is a pending request for the same module ID. Cancel the pending request first with cancelPendingModule, then remove.

Cancel a pending module

If you need to abort a module addition or update during the timelock period, cancel it. Requires: CANCEL_MODULE role.

Disallow a module on a target

Revoke a module’s authorization on a specific target without removing it from the registry.

Update the timelock duration

Change the global timelock duration for future module operations. Requires: UPDATE_TIMELOCK role.

Next steps

Configure fees

Set up fee structures for your Multi-Vehicle.

Configure rewards

Capture and distribute additional protocol rewards with interceptors.