ModuleKit
Build
Module Basics

Module Basics

A module can be broken down into three different domains:

  1. Config: Handles configurations on the module, such as installation and uninstallation
  2. Business logic: Handles the core logic of the module, depending on the module type
  3. Metadata: Additional data that is used to identify and correctly use a module

This page covers domains 1 and 3 since they are the same across different module types. For more information on domain 2, read through the specific module type pages.

Building a module

To build a compliant module you need to ensure that it:

  • Inherits from the right module base, depending on its type.
  • Implements the required functions of the interface.

An example of a compliant module (without actual logic) looks like this:

contract ModuleExample is ERC7579ModuleBase {
    /*//////////////////////////////////////////////////////////////////////////
                                     CONFIG
    //////////////////////////////////////////////////////////////////////////*/
 
    /* Initialize the module with the given data
     * @param data The data to initialize the module with
     */
    function onInstall(bytes calldata data) external override {
        _setModuleData(data);
    }
 
    /* De-initialize the module with the given data
     * @param data The data to de-initialize the module with
     */
    function onUninstall(bytes calldata data) external override {
        _removeModuleData(data);
    }
 
    /*
     * Check if the module is initialized
     * @param smartAccount The smart account to check
     * @return true if the module is initialized, false otherwise
     */
    function isInitialized(address smartAccount) external view returns (bool) {
        return _isModuleInitialized(smartAccount);
    }
 
    /*//////////////////////////////////////////////////////////////////////////
                                     MODULE LOGIC
    //////////////////////////////////////////////////////////////////////////*/
 
    ...
 
    /*//////////////////////////////////////////////////////////////////////////
                                     METADATA
    //////////////////////////////////////////////////////////////////////////*/
 
    /**
     * The name of the module
     * @return name The name of the module
     */
    function name() external pure returns (string memory) {
        return "ModuleExample";
    }
 
    /**
     * The version of the module
     * @return version The version of the module
     */
    function version() external pure returns (string memory) {
        return "0.0.1";
    }
 
    /*
        * Check if the module is of a certain type
        * @param typeID The type ID to check
        * @return true if the module is of the given type, false otherwise
        */
    function isModuleType(uint256 typeID) external pure override returns (bool) {
        return typeID == TYPE_VALIDATOR || typeID == TYPE_EXECUTOR || typeID == TYPE_FALLBACK || typeID == TYPE_HOOK;
    }
 
    /**
     * Get the module types
     * @return moduleTypes The bit-encoded module types
     */
    function getModuleTypes() external view returns (EncodedModuleTypes) {}
}

onInstall

This function is called when the module is installed on a smart account. It is given the data that was passed to the installModule function. The module can use this data to initialize itself and should revert if the module is already initialized for the calling account.

onUninstall

This function is called when the module is uninstalled from a smart account. It is given the data that was passed to the uninstallModule function. The module can use this data to de-initialize itself and should revert if the module is not initialized for the calling account. It is also very important that the module cleans up all data for that account. Not doing so could cause unexpected behavior and even security vulnerabilities if a module is uninstalled and then reinstalled.

isInitialized

This function is called to check if the module is initialized for a given smart account. It should return true if the module is initialized and false otherwise.

name

This function is called to get the name of the module. It should return a string with the name of the module.

version

This function is called to get the version of the module. It should return a string with the version of the module.

isModuleType

This function is called to check if the module is of a certain type. It should return true if the module is of the given type and false otherwise.

getModuleTypes

This function is called to get the module types. It should return a bit-encoded module types.