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();