Skip to main content

RAIModuleFactory

Inherits: Ownable2Step

Title: RAIModuleFactory

Deploys and manages isolated RAI modules (Subscription, Credit, etc.)

Uses uint256 module IDs for infinite expansion without factory redeployment. This enables a plug-and-play architecture where new module types can be added by simply deploying an implementation and calling setImplementation(). Module ID System:

  • 0 = SUBSCRIPTION
  • 1 = CREDIT
  • 2+ = Future modules (Usage, Tiered, Pay-per-View, etc.) Plug-and-Play Flow:
  1. Deploy new module implementation (e.g., UsageModule)
  2. Owner calls setImplementation(moduleId, implementationAddress)
  3. Merchants can immediately deploy modules via deployModule(moduleId)

State Variables

paymentProcessor

Global PaymentProcessor used by all merchant modules

address public immutable paymentProcessor

implementations

Mapping: moduleId => implementation logic address

mapping(uint256 => address) public implementations

moduleOf

Mapping: merchant => moduleId => their deployed clone

mapping(address => mapping(uint256 => address)) public moduleOf

merchantRegistry

Optional MerchantRegistry address for profile verification

address public merchantRegistry

requireMerchantProfile

Whether to require merchant profile registration before deployment

bool public requireMerchantProfile

Functions

constructor

constructor(address _paymentProcessor) Ownable(msg.sender);

setImplementation

Sets the implementation logic for a specific module type.

Can be called multiple times to update implementations (e.g., for upgrades). This enables infinite expansion - new module types can be added without redeploying the factory.

function setImplementation(uint256 moduleId, address impl) external onlyOwner;

Parameters

NameTypeDescription
moduleIduint256The module ID (0 = SUBSCRIPTION, 1 = CREDIT, 2+ = future modules)
impladdressThe address of the logic contract

setMerchantRegistry

Sets the MerchantRegistry address (optional).

Can be set to address(0) to disable merchant registry checks.

function setMerchantRegistry(address _merchantRegistry) external onlyOwner;

Parameters

NameTypeDescription
_merchantRegistryaddressThe address of the MerchantRegistry contract

setRequireMerchantProfile

Sets whether merchant profile registration is required.

Only effective if merchantRegistry is set to a non-zero address.

function setRequireMerchantProfile(bool _requireMerchantProfile) external onlyOwner;

Parameters

NameTypeDescription
_requireMerchantProfileboolWhether to require merchant profile registration

deployModule

Deploys a module of a specific type for the merchant.

Steps:

  1. Validate implementation is set
  2. Enforce one module per merchant per module type
  3. Clone the implementation (EIP-1167)
  4. Initialize with (merchant, paymentProcessor)
  5. Register with PaymentProcessor
  6. Store mapping
function deployModule(uint256 moduleId) external returns (address module);

Parameters

NameTypeDescription
moduleIduint256The type of module to deploy (0 = SUBSCRIPTION, 1 = CREDIT, etc.)

Returns

NameTypeDescription
moduleaddressThe address of the new proxy

getModule

Returns the module belonging to a merchant for a specific module type

function getModule(address merchant, uint256 moduleId) external view returns (address);

Parameters

NameTypeDescription
merchantaddressMerchant address
moduleIduint256Module type ID

Returns

NameTypeDescription
<none>addressThe module address, or address(0) if not deployed

Events

ModuleCreated

event ModuleCreated(address indexed merchant, address indexed module, uint256 indexed moduleId);

ImplementationUpdated

event ImplementationUpdated(uint256 indexed moduleId, address indexed implementation);

MerchantRegistryUpdated

event MerchantRegistryUpdated(address indexed merchantRegistry);

RequireMerchantProfileUpdated

event RequireMerchantProfileUpdated(bool requireMerchantProfile);

Errors

InvalidAddress

error InvalidAddress();

NotAContract

error NotAContract();

ModuleAlreadyExists

error ModuleAlreadyExists();

ImplementationNotSet

error ImplementationNotSet();

MerchantNotRegistered

error MerchantNotRegistered();