Skip to content

IFIFFactory Contract

The IFIFFactory contract serves as the central deployment and management hub for the IFIF ecosystem. It implements a clone-based deployment pattern for gas-efficient project creation and manages shared protocol resources including implementation contracts, whitelists, and DEX integration.

Overview

Contract Address: contracts/src/utils/IFIFFactory.sol
License: GPL-3.0-only
Solidity Version: 0.8.19

Key Features

  • Clone-Based Deployment: Gas-efficient project deployment using LibClone deterministic patterns
  • Mandatory Deployment Fees: Configurable fee collection in ETH or ERC20 tokens for all deployments
  • Implementation Management: Centralized control of IFIF and token contract implementations
  • Shared Resource Management: Unified whitelist, DEX router, and metadata configuration
  • Role-Based Access Control: Hierarchical permissions for administrative functions
  • Project Lifecycle Control: Stage transition validation and project finalization
  • Token Deployment: Automated token contract creation and minting for successful projects

Core Components

Implementation Contracts

IFIF Implementation

address public implementation;
  • Purpose: Master contract for IFIF project clones
  • Management: Updated by admin role for protocol upgrades
  • Usage: Template for all new project deployments

Token Implementation

address public tokenImplementation;
  • Purpose: Master contract for project token deployments
  • Management: Updated by admin role for token upgrades
  • Usage: Template for successful project token creation

Shared Resources

Whitelist Contract

address public whitelist;
  • Purpose: Merkle tree-based access control for all projects
  • Scope: Shared across entire protocol
  • Management: Updated by admin role

DEX Router

address public dexRouter;
  • Purpose: Automated market making and liquidity provision
  • Integration: Used by projects for DEX pair creation
  • Management: Updated by admin role

Base URI

string public baseURI;
  • Purpose: NFT metadata base URL for all projects
  • Format: {baseURI}/{projectId}/{tokenId}
  • Management: Updated by admin role

Deployment Fees

mapping(address token => uint256 feeAmount) public deploymentFees;
  • Purpose: Maps payment tokens to required deployment fee amounts
  • Configuration: Set by admin role for each supported payment token
  • Payment: Use address(0) for ETH fees, token addresses for ERC20 fees
  • Requirement: All deployments must pay configured fee - no free deployments allowed

Core Functions

Project Deployment

deploy()

function deploy(
    IIFIF.Config calldata config,
    IIFIF.NextConfig calldata nextConfig,
    bytes calldata configSignature,
    bytes calldata nextConfigSignature,
    string calldata projectName,
    string calldata projectSymbol,
    address paymentToken
) external payable returns (address)

Purpose: Deploys a new IFIF project using the clone pattern with EIP-712 signature validation and mandatory fee collection.

Parameters:

  • config: Core project configuration (funding targets, timings, token parameters)
  • nextConfig: Mutable configuration (stakeholders, fees, pricing)
  • configSignature: EIP-712 signature for config validation
  • nextConfigSignature: EIP-712 signature for nextConfig validation
  • projectName: Human-readable name for project and NFT collection
  • projectSymbol: Short symbol identifier for project
  • paymentToken: Token address to pay deployment fee with (address(0) for ETH)

Access: Public payable function (signature validation provides security)

Process:

  1. Validates project ID is not already deployed
  2. Validates implementation contract is available
  3. Collects mandatory deployment fee in specified payment token
  4. Creates deterministic clone using LibClone
  5. Initializes project with provided configuration and signatures
  6. Registers project in deployment tracking
  7. Emits Deployed and DeploymentFeeCollected events

Returns: Address of newly deployed project contract

Fee Requirements:

  • ETH Payment: Call with {value: deploymentFee} when paymentToken is address(0)
  • Token Payment: Approve factory for token transfer, call with msg.value = 0
  • Mandatory: Fee must be configured and paid - no free deployments allowed

Validations:

  • Project ID uniqueness
  • Implementation availability
  • Valid EIP-712 signatures for both config structs
  • Deployment fee configured and sufficient payment provided

Project Management

mintToken()

function mintToken(uint256 mintAmount) external returns (address)

Purpose: Creates token contract and mints tokens for successful projects during deposit phase.

Parameters:

  • mintAmount: Amount of tokens to mint for distribution and liquidity

Access: Restricted to deployed project contracts only

Process:

  1. Validates caller is a deployed project
  2. Validates token implementation is available
  3. Creates deterministic clone of token implementation (first call only)
  4. Initializes token with project as minter (first call only)
  5. Mints additional tokens for subsequent distributor deposits
  6. Updates deployment details with token address
  7. Emits TokenDeployed and TokenMinted events

Returns: Address of the project's token contract

Usage: Called internally by project contracts during the deposit phase when distributors provide tokens for rewards and liquidity

updateDeploymentDetails()

function updateDeploymentDetails(
    uint256 projectId,
    string memory projectName,
    string memory projectSymbol
) external

Purpose: Updates project name and symbol during INIT stage.

Parameters:

  • projectId: Unique project identifier
  • projectName: New project name
  • projectSymbol: New project symbol

Access: Restricted to project owner during INIT stage only

Usage: Allows project owner to modify metadata before sales begin

View Functions

Core Configuration

implementation() → address

Returns the current project implementation contract address used for cloning new projects.

tokenImplementation() → address

Returns the current project token implementation contract address used for deploying project tokens.

whitelist() → address

Returns the whitelist contract address used for sale access control.

dexRouter() → address

Returns the DEX router contract address used for liquidity operations.

baseURI() → string

Returns the base URI for NFT metadata across all projects.

Role Management

getRoleHelper() → address

Returns the current role helper contract address that implements access control functionality. Inherited from the IRole interface.

Deployment Information

deployments(uint256 projectId) → address

Returns the project contract address for a given project ID.

Parameters:

  • projectId: Unique project identifier

Returns: Address of the deployed project contract

deploymentDetails(address project) → (uint256, address, address, bool, string, string)

Returns detailed deployment information for a project.

Parameters:

  • project: Address of the deployed project contract

Returns:

  • id: Unique project identifier
  • currentImplementation: Implementation contract used for deployment
  • token: Address of project token (if deployed)
  • isDeployed: Whether the project has been deployed
  • name: Human-readable project name
  • symbol: Short project symbol

ERC165 Support

supportsInterface(bytes4 interfaceId) → bool

Checks if the contract implements a specific interface ID.

Parameters:

  • interfaceId: The interface identifier as defined in ERC165

Returns: True if the contract implements the queried interface

Note: Supports IIFIFFactory and IRole interfaces

Administrative Functions

updateCore()

function updateCore(
    address _whitelist,
    address _dexRouter,
    address _roles
) external onlyAdmin

Purpose: Updates core system contracts shared across all projects.

Parameters:

  • _whitelist: New whitelist contract address
  • _dexRouter: New DEX router address
  • _roles: New role management contract address

Access: Restricted to ADMIN_ROLE holders

Validations:

  • Non-zero addresses for all parameters
  • Emits CoreUpdated event

updateImplementation()

function updateImplementation(address newImplementation) external onlyAdmin

Purpose: Updates the IFIF implementation contract for new deployments.

Parameters:

  • newImplementation: Address of new IFIF implementation

Access: Restricted to ADMIN_ROLE holders

Validations:

  • Non-zero address
  • Contract implements IIFIF interface
  • Emits ImplementationUpdated event

updateTokenImplementation()

function updateTokenImplementation(address newTokenImplementation) external onlyAdmin

Purpose: Updates the token implementation for new token deployments.

Parameters:

  • newTokenImplementation: Address of new token implementation

Access: Restricted to ADMIN_ROLE holders

Validations:

  • Non-zero address
  • Contract implements IIFIFToken interface
  • Emits TokenImplementationUpdated event

updateBaseURI()

function updateBaseURI(string calldata newBaseURI) external onlyAdmin

Purpose: Updates the base URI for NFT metadata across all projects.

Parameters:

  • newBaseURI: New base URI string

Access: Restricted to ADMIN_ROLE holders

Emits: BaseURIUpdated event

updateDeploymentFee()

function updateDeploymentFee(address paymentToken, uint256 feeAmount) external onlyAdmin

Purpose: Sets or updates the deployment fee for a specific payment token.

Parameters:

  • paymentToken: Token address to set fee for (address(0) for ETH)
  • feeAmount: Fee amount required for deployment in the specified token

Access: Restricted to ADMIN_ROLE holders

Usage:

  • Configure ETH fee: updateDeploymentFee(address(0), ethFeeAmount)
  • Configure token fee: updateDeploymentFee(tokenAddress, tokenFeeAmount)
  • Remove fee: updateDeploymentFee(tokenAddress, 0) (disables deployment with that token)

Emits: DeploymentFeeUpdated event

updateRoleHelper()

function updateRoleHelper(address roleHelper) external onlyAdmin

Purpose: Updates the role helper contract that implements access control functionality.

Parameters:

  • roleHelper: Address of new role helper contract implementing IAccessControl

Access: Restricted to ADMIN_ROLE holders

Validations:

  • Non-zero address
  • Contract implements IAccessControl interface
  • Emits RoleHelperUpdated event

Note: Inherited from the Role contract, provides centralized role management

upgradeDeployment()

function upgradeDeployment(uint256 projectId, bytes calldata data) external onlyAdmin

Purpose: Upgrades a deployed project to a new implementation using UUPS pattern.

Parameters:

  • projectId: Unique project identifier to upgrade
  • data: Optional initialization data for the new implementation

Access: Restricted to ADMIN_ROLE holders

Requirements:

  • Project must be in INIT stage (upgrades not allowed during active sales or claim)

Process: Performs UUPS upgrade on the specified project contract

call()

function call(uint256 projectId, bytes calldata data, uint256 value) external onlyManager returns (bytes memory)

Purpose: Executes arbitrary function calls on deployed project contracts for administrative operations.

Parameters:

  • projectId: Unique identifier of the target project contract
  • data: Encoded function call data to execute on the project
  • value: ETH value to send with the call (for payable functions)

Access: Restricted to MANAGER_ROLE holders

Returns: Return data from the executed function call

Usage: Emergency actions, configuration updates, or privileged operations requiring factory authority

withdraw()

function withdraw(address token, uint256 amount) external onlyAdmin

Purpose: Withdraws accumulated fees and tokens from the factory contract.

Parameters:

  • token: Address of the ERC20 token to withdraw (or address(0) for ETH)
  • amount: Amount of tokens/ETH to withdraw to admin address

Access: Restricted to ADMIN_ROLE holders

Usage: Treasury management, fee collection, emergency fund recovery

Emits: Withdrew event

Query Functions

deployments()

function deployments(uint256 projectId) external view returns (address)

Purpose: Retrieves project contract address by ID.

Parameters:

  • projectId: Unique project identifier

Returns: Project contract address or zero address if not found

deploymentDetails()

function deploymentDetails(address project) external view returns (
    uint256 id,
    address currentImplementation,
    address token,
    bool isDeployed,
    string memory name,
    string memory symbol
)

Purpose: Retrieves detailed deployment information for a project.

Parameters:

  • project: Project contract address

Returns: Complete deployment struct with all project metadata

deploymentFees()

function deploymentFees(address token) external view returns (uint256)

Purpose: Retrieves the deployment fee for a specific payment token.

Parameters:

  • token: Token address to query fee for (address(0) for ETH)

Returns: Fee amount required for deployment in the specified token

Core Resource Getters

function implementation() external view returns (address);
function tokenImplementation() external view returns (address);
function whitelist() external view returns (address);
function dexRouter() external view returns (address);
function baseURI() external view returns (string memory);

Purpose: Access current core system contract addresses and configuration.

DEX Integration

The IFIFFactory provides infrastructure for DEX integration but does not automatically handle liquidity provision. Projects handle their own DEX interactions through the shared DEX router.

Shared DEX Router

The factory maintains a reference to a DEX router contract that projects can use for:

  • Token Trading: Creating trading pairs for project tokens
  • Liquidity Operations: Adding/removing liquidity as needed
  • Price Discovery: Market-based token pricing mechanisms

Integration Notes

  • Automatic Process: Projects automatically create DEX pairs and add liquidity during token deposit
  • Shared Resource: All projects use the same DEX router configuration
  • Standardized Integration: Consistent DEX integration across all projects

Security Architecture

Access Control Hierarchy

ADMIN_ROLE
├── Update implementation contracts
├── Update core system contracts (whitelist, DEX router, roles)
├── Manage base URI configuration
├── Configure deployment fees for different payment tokens
├── Upgrade deployed projects
└── Withdraw accumulated fees and tokens from factory
 
MANAGER_ROLE  
├── Execute arbitrary function calls on deployed project contracts
├── Validate EIP-712 signatures for project configuration
├── Update whitelist merkle tree roots
└── Required for project initialization and config updates
 
DISTRIBUTOR_ROLE
├── Required for project distributors during initialization
├── Validated during project configuration
└── Enables deposit functionality in project contracts

Deployment Security

  • Deterministic Addresses: CREATE2 pattern for predictable deployments
  • Implementation Validation: Ensures implementation contracts meet interface requirements
  • Parameter Validation: Comprehensive validation of all deployment parameters
  • Access Control: Role-based restrictions on critical functions

Upgrade Safety

  • UUPS Pattern: Implementation contracts use UUPS upgradeable pattern
  • Centralized Control: Factory manages upgrades for all deployed projects
  • Validation Checks: Ensures upgrade safety and compatibility

Events

Core Events

event Deployed(uint256 indexed projectId, address indexed project);
 
event TokenDeployed(uint256 indexed projectId, address indexed token);
 
event TokenMinted(uint256 indexed projectId, uint256 amount);
 
event ImplementationUpdated(address indexed newImplementation);
 
event TokenImplementationUpdated(address indexed newTokenImplementation);
 
event CoreUpdated(address indexed newWhitelist, address indexed newDexRouter);
 
event DeploymentDetailsUpdated(uint256 indexed projectId, string newProjectName, string newProjectSymbol);
 
event BaseURIUpdated(string newBaseURI);
 
event DeploymentFeeUpdated(address indexed paymentToken, uint256 feeAmount);
 
event DeploymentFeeCollected(uint256 indexed projectId, address indexed payer, address indexed paymentToken, uint256 amount);
 
event Withdrew(address indexed to, address indexed token, uint256 amount);

Integration Patterns

Project Deployment Flow

// Deploy new project with manager signatures and deployment fee
const ethFee = await factory.deploymentFees(ethers.constants.AddressZero);
 
const deployTx = await factory.deploy(
  config,              // Core configuration
  nextConfig,          // Mutable configuration  
  configSignature,     // EIP-712 signature for config from manager
  nextConfigSignature, // EIP-712 signature for nextConfig from manager
  "Project Name",      // Project name
  "PROJ",             // Project symbol
  ethers.constants.AddressZero, // Payment token (address(0) for ETH)
  { value: ethFee }    // Pay deployment fee in ETH
);
 
// Or deploy with ERC20 token fee
const tokenFee = await factory.deploymentFees(tokenAddress);
await token.approve(factory.address, tokenFee);
 
const deployTx = await factory.deploy(
  config,
  nextConfig,
  configSignature,
  nextConfigSignature,
  "Project Name",
  "PROJ",
  tokenAddress        // Payment token address
  // No value needed for token payments
);
 
// Get deployed project address from event
const receipt = await deployTx.wait();
const deployedEvent = receipt.events.find(e => e.event === 'Deployed');
const projectAddress = deployedEvent.args.project;

Token Deployment and Minting (Called by Project)

// Project contract calls factory to mint tokens during deposit phase
// This happens automatically when distributors deposit tokens
const project = await ethers.getContractAt("IFIF", projectAddress);
 
// Token creation and minting happens automatically during project.deposit()
// First deposit creates the token, subsequent deposits mint additional tokens
 
// Get token address from factory deployment details
const details = await factory.deploymentDetails(projectAddress);
const tokenAddress = details.token;
const tokenContract = await ethers.getContractAt("IIFIFToken", tokenAddress);

Project Upgrade

// Admin upgrades project implementation
const upgradeTx = await factory.upgradeDeployment(
  projectId,
  "0x" // Optional initialization data
);

Gas Optimization

Clone Pattern Benefits

  • Deployment Cost: ~90% reduction compared to full contract deployment
  • Deterministic Addresses: CREATE2 for predictable project addresses
  • Shared Logic: Implementation reused across all projects

Storage Efficiency

  • Minimal Storage: Factory stores only essential project metadata
  • Delegated Storage: Project-specific data stored in individual contracts
  • Shared Resources: Common resources shared across all projects

Testing Coverage

The IFIFFactory contract maintains comprehensive test coverage:

  • Deployment scenarios: Valid and invalid project deployments
  • Access control: Role-based permission testing
  • Finalization logic: Success and failure path validation
  • Address prediction: Deterministic address verification
  • Administrative functions: Implementation and resource updates
  • Edge cases: Boundary conditions and error scenarios
  • Integration tests: End-to-end deployment and finalization flows

Deployment Configuration

Network-Specific Settings

// Example deployment configuration
const factoryConfig = {
  roles: "0x...",           // Roles contract address
  whitelist: "0x...",       // Whitelist contract address
  dexRouter: "0x...",       // DEX router address
  baseURI: "https://api.ifif.io/metadata",
  implementations: {
    ifif: "0x...",          // IFIF implementation
    token: "0x..."          // Token implementation
  },
  deploymentFees: {
    eth: ethers.utils.parseEther("0.01"),     // ETH fee amount
    usdc: ethers.utils.parseUnits("10", 6),   // USDC fee amount
    // Add other supported payment tokens
  }
};
 
// Configure deployment fees after factory deployment
await factory.updateDeploymentFee(ethers.constants.AddressZero, factoryConfig.deploymentFees.eth);
await factory.updateDeploymentFee(usdcAddress, factoryConfig.deploymentFees.usdc);

Upgrade Considerations

  • Implementation Updates: Test thoroughly before updating implementations
  • Backwards Compatibility: Ensure new implementations maintain interface compatibility
  • Migration Planning: Consider migration strategies for existing projects

For detailed deployment instructions and configuration examples, see the Deployment Guide.