Skip to main content

Base IModule

Overview

The Core Module Interface (IModule) serves as the foundation for all module types in the ERC-7579 smart account system. All specialized modules (Validator, Executor, Hook, Fallback) must implement this base interface.

Interface Definition

interface IModule {
error AlreadyInitialized(address smartAccount);
error NotInitialized(address smartAccount);

function onInstall(bytes calldata data) external;
function onUninstall(bytes calldata data) external;
function isModuleType(uint256 moduleTypeId) external view returns (bool);
function isInitialized(address smartAccount) external view returns (bool);
}

Core Functions

onInstall

Called when installing the module on a smart account.

function onInstall(bytes calldata data) external;
  • Must revert if module is already initialized
  • Handles initialization logic using provided data
  • Typically sets up initial state for the account

onUninstall

Called when removing the module from a smart account.

function onUninstall(bytes calldata data) external;
  • Must revert if module is not initialized
  • Handles cleanup and state removal
  • Ensures proper module deactivation

isModuleType

Verifies if the module matches a specific type.

function isModuleType(uint256 moduleTypeId) external view returns (bool);
  • Returns true if module matches the specified type
  • Module types are defined as constants:
    • MODULE_TYPE_VALIDATOR = 1
    • MODULE_TYPE_EXECUTOR = 2
    • MODULE_TYPE_FALLBACK = 3
    • MODULE_TYPE_HOOK = 4

isInitialized

Checks if the module is initialized for a specific account.

function isInitialized(address smartAccount) external view returns (bool);
  • Returns true if module is active for the account
  • Used for validation before operations

Implementation Example

abstract contract BaseModule is IModule {
// Tracks initialized accounts
mapping(address => bool) internal initializedAccounts;

function onInstall(bytes calldata data) external virtual {
if (initializedAccounts[msg.sender]) {
revert AlreadyInitialized(msg.sender);
}
initializedAccounts[msg.sender] = true;

// Additional initialization logic
}

function onUninstall(bytes calldata data) external virtual {
if (!initializedAccounts[msg.sender]) {
revert NotInitialized(msg.sender);
}
initializedAccounts[msg.sender] = false;

// Additional cleanup logic
}

function isInitialized(address smartAccount) public view virtual returns (bool) {
return initializedAccounts[smartAccount];
}
}

Best Practices

  1. State Management

    • Use clear state variables for initialization tracking
    • Implement proper access control
    • Handle state changes atomically
  2. Error Handling

    • Use custom errors for better gas efficiency
    • Include descriptive error messages
    • Validate all inputs
  3. Gas Optimization

    • Use mappings for O(1) lookups
    • Minimize storage operations
    • Batch operations when possible

Security Considerations

  1. Access Control

    • Only allow authorized accounts to install/uninstall
    • Validate caller permissions
    • Implement proper initialization checks
  2. State Consistency

    • Ensure atomic state changes
    • Prevent reentrant calls
    • Validate state transitions
  3. Upgrade Safety

    • Plan for potential upgrades
    • Maintain state consistency
    • Document state variables