RealTokenFactory.sol
Overview
RealTokenFactory standardizes deployment of RealFractionalToken series. The base version uses a plain new constructor for simplicity; you can extend it to CREATE2 or minimal proxies (clones) if you need deterministic addresses or cheaper deployments.
Responsibilities
Deploy a new token with the correct admin and compliance registry wired in the constructor.
Emit a structured event so indexers (subgraphs, ETLs) can track the new series.
Contract Boundary and Data Flow
(deployer/admin) ──> RealTokenFactory.deployToken(name, symbol, admin, registry)
│
└─ deploys RealFractionalToken(name, symbol, admin, registry)
│
└─ emits TokenDeployed(token, name, symbol, admin, registry)Key Components
Constructor Deployment: new RealFractionalToken(...) (straightforward and auditable).
Events: TokenDeployed includes all relevant metadata to bootstrap off-chain systems.
Optional Extensions (Patterns)
CREATE2 (Deterministic): pre-compute addresses for downstream wiring (e.g., granting roles before the token exists).
Add salt = keccak256(abi.encode(...)) and a bytecode deploy wrapper.
Minimal Proxy (Clones): if you deploy many series, use OZ Clones to reduce gas.
Convert token to an initialize pattern (or an upgradeable proxy) and add clone/initialize flow in the factory.
Registry Pinning: add allowlist of registries the factory can use.
Interactions With Other Modules
After deploying the token, your OfferingFactory (or ops script) should:
Grant MINTER_ROLE to RealOffering (or to the address predicted with CREATE2).
Optionally, grant BURNER_ROLE to redemption contracts or admin.
Grant PAUSER_ROLE to ops/multisig.
Security Considerations
If you add access control to the factory (e.g., only approved issuers), gate deployToken.
Validate constructor args (non-zero admin/registry).
If you adopt CREATE2, ensure salts don’t collide across issuers.
Gas Notes
The simple new path has predictable gas and minimal runtime overhead.
Clones reduce deployment gas drastically but add an initializer call—be careful with initializer-only-once guards.
Minimal Usage Examples
// deploy a new series
address token = factory.deployToken(
"Asset A Fractions", "ASST-A", admin, complianceRegistry
);
// wire roles to primary market
RealFractionalToken(token).grantRole(MINTER_ROLE, offering);Example: CREATE2 Sketch (if you choose to extend)
// pseudo: using a deployer that supports create2
function deployTokenDeterministic(
string calldata name_,
string calldata symbol_,
address admin_,
address registry_,
bytes32 salt
) external returns (address token) {
// build creationCode: type(RealFractionalToken).creationCode ++ encoded ctor args
// call create2(salt)
}How They Fit Together
Factory deploys Token
RealTokenFactory.deployToken(...) → emits TokenDeployed.
Grant Roles
Admin grants MINTER_ROLE to RealOffering (primary), RealStakingDistributor (yield), RealLending (liquidations or redemptions, if needed).
Operations
Transfers, mints, and burns always call into the Compliance Registry.
Ops can pause during critical events.
Evolution
Swap out registry as rules evolve (REGISTRY_ADMIN_ROLE).
Introduce fees/timelocks/snapshots as optional, contained changes.
RealTokenFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {RealFractionalToken} from "./RealFractionalToken.sol";
/// @title RealTokenFactory
/// @notice Deploys new RealFractionalToken contracts for asset series.
/// @dev Keeps deployments standardized with consistent admin and registry setup.
contract RealTokenFactory {
/// @notice Emitted when a new token is deployed.
event TokenDeployed(
address indexed token,
string name,
string symbol,
address indexed admin,
address indexed registry
);
/// @notice Deploy a new RealFractionalToken for a specific asset.
/// @param name_ Token name (e.g. "Asset A Fractions")
/// @param symbol_ Token symbol (e.g. "ASST-A")
/// @param admin_ Address to receive DEFAULT_ADMIN_ROLE and other roles
/// @param registry_ Address of the compliance registry
/// @return token Address of the newly deployed RealFractionalToken
function deployToken(
string calldata name_,
string calldata symbol_,
address admin_,
address registry_
) external returns (address token) {
RealFractionalToken t = new RealFractionalToken(
name_,
symbol_,
admin_,
registry_
);
token = address(t);
emit TokenDeployed(token, name_, symbol_, admin_, registry_);
}
}Last updated