Register a Module

Modules are smart contracts that are registered in the "Module Registry" and that perform specific validation logic on attestations before they are issued into the registry.

The Module mechanism may change in the future, following Verax Improvement Proposal #5 and what we call "Modules V2".

Module creation

Modules are intended to perform a single specific function. They should be designed to be minimalistic, atomic, and reusable. Modules can be chained together in series so that they are executed in order, with any module in the chain being able to prevent an attestation being issued to the registry by simply reverting if its verification checks fail.

To create a module, you must deploy a smart contract that inherits the AbstractModule abstract contract, which looks like this:

abstract contract AbstractModule {
  function run(
    AttestationPayload memory attestationPayload,
    bytes memory validationPayload,
    address txSender,
    uint256 value
  ) public virtual returns (bytes[] memory moduleValidationPayload);
}

The run function accepts four arguments:

  1. attestationPayload, the raw attestation data that will be stored in the registry

  2. validationPayload, validation logic that the module needs to execute its verification logic

  3. txSender, the address of the initial transaction sender

  4. value, the amount of ETH paid to get this attestation

The validationPayload can be any data, which may encompass fields from the attestation metadata or additional data such as ZKP proof, a signature, merkle proof, and so on.

As well as implementing the AbstractModule interface, the module contract must also implement the IERC165Upgradeable interface, which involves including this function:

function supportsInterface(bytes4 interfaceID) public pure override returns (bool) {
  return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId;
}

Module registration

Module registration takes 3 parameters, defined as follows:

ParameterDescription

name

A descriptive name for the module that's stored on-chain

description

A link to an off-chain document that describes the module

moduleAddress

The address of the module smart contract

Manually registering a deployed Module in the ModuleRegistry contract

Once you have deployed your module contract, you can then register it in the ModuleRegistry contract using the register function:

function register(
    string memory name,
    string memory description,
    address moduleAddress
);

A few caveats: a module contract must be first deployed and cannot be registered twice under different names, and it must implement the interfaces described above. Also, the name parameter must not be empty.

Using a blockchain explorer

Instead of crafting the smart contract call by hand, you can benefit from a chain explorer interface. Let's use the Linea Sepolia explorer, Lineascan.

  1. Retrieve the ModuleRegistry contract address from the project README

  2. Access the ModuleRegistry contract on Lineascan

  3. Go to the "Contract" tab

  4. Connect your allow-listed wallet and fill the register form with the parameters described above

  5. Send the transaction

Using the official Verax SDK

We have seen rather manual ways to register a Module, now let's focus on the easiest way: via the Verax SDK.

Check this page to discover how to instantiate the Verax SDK.

Once you have an SDK instance, you can register a Module like this:

await veraxSdk.module.register(
    "ExampleModule",
    "This Module is used as an example",
    "0xda14ac2b6fb17cca948ea74a051af75c92998643",
);

To dive deeper on exactly how the ModuleRegistry contract works, you can check out the source code on GitHub.

Once you have deployed one or more schemas and optionally also deployed one or more modules, you are ready to register a portal and tie them all together so that you can issue your first attestations.

Last updated