Skip to main content

Overview

The RektHubFactory is the central hub of the RektHub protocol. It’s your single entry point for creating creator tokens, trading, and managing the entire token lifecycle. Think of it as the conductor of an orchestra, coordinating token creation, routing trades, and managing graduations across the creator economy.
For Integrators: Always use the Factory as your primary interface. It ensures consistency, proper fee distribution, and seamless cross-contract interactions.

Purpose & Architecture

What It Does

  • Token Creation: Deploys new creator tokens with bonding curves
  • Trade Routing: Routes buy/sell orders to the correct bonding curve
  • Fee Management: Collects platform fees
  • Graduation Control: Manages token migration to DEX (owner-only)
  • Address Discovery: Maps tokens to their bonding curves

Why It Matters

The Factory pattern provides:
  • Gas Efficiency: Uses minimal proxies (EIP-1167) to clone implementations
  • Isolation: Each token gets its own bonding curve with isolated state
  • Upgradeability: New features can be added without affecting existing tokens (not an upgradeable contract though)
  • Single Source of Truth: All critical operations go through one audited contract

Key Functions

Token Creation

createToken

name
string
required
Token name (e.g., “Creator Coin”)
symbol
string
required
Token symbol (e.g., “CRTR”)
tokenURI
string
required
URI pointing to token metadata JSON
Returns:
  • tokenAddress: Address of the deployed token
  • curveAddress: Address of the bonding curve
Events Emitted:
  • TokenCreated
Example:
function createToken(
    string calldata name,
    string calldata symbol,
    string calldata tokenURI
) external payable returns (address tokenAddress, address curveAddress);
const tx = await factory.createToken('Creator Coin', 'CRTR', 'ipfs://Qm...', {
	value: creationFee,
});

const receipt = await tx.wait();

const event = receipt.logs
	.map((log) => factory.interface.parseLog(log))
	.find((e) => e?.name === 'TokenCreated');

console.log('Token address:', event.args.tokenAddress);
console.log('Curve address:', event.args.curveAddress);
Metadata Best Practices: Host your tokenURI on IPFS or Arweave for permanence. Include name, description, image, and social links. See Token Contract for JSON format.

createTokenDeterministic

Create a token with a vanity address using CREATE2.
name
string
required
Token name
symbol
string
required
Token symbol
tokenURI
string
required
Metadata URI
salt
bytes32
required
CREATE2 salt (pre-mined for vanity address)
Returns:
  • tokenAddress: Deterministic token address
  • curveAddress: Deterministic curve address
Events Emitted:
  • TokenCreated
Example:
const salt = ethers.id('my-vanity-salt');

const [predictedToken, predictedCurve] = await factory.predictAddresses(salt);
console.log('Will create token at:', predictedToken);

const code = await provider.getCode(predictedToken);
if (code !== '0x') {
	throw new Error('Address already occupied!');
}

const tx = await factory.createTokenDeterministic(
	'Vanity Token',
	'VNTY',
	'ipfs://Qm...',
	salt,
	{ value: creationFee }
);
Address Collision: Always check if the predicted address is available before calling createTokenDeterministic. The transaction will revert if the address is occupied.

predictAddresses

Preview the addresses that will be created with a given salt.
salt
bytes32
required
CREATE2 salt
Returns:
  • predictedToken: Token address that will be created
  • predictedCurve: Curve address that will be created
Example:
const salt = ethers.id('test-salt');
const [tokenAddr, curveAddr] = await factory.predictAddresses(salt);

console.log('Future token address:', tokenAddr);
console.log('Future curve address:', curveAddr);

Trading Functions

buy

Purchase creator tokens from any deployed curve.
token
address
required
Address of the token to buy
minTokensOut
uint256
required
Minimum tokens expected (slippage protection)
Returns:
  • tokensReceived: Actual amount of tokens received
Events Emitted:
  • TokenPurchased
Example:
const curveAddress = await factory.getCurve(tokenAddress);
const curve = new ethers.Contract(curveAddress, CURVE_ABI, provider);

const amountToSpend = ethers.parseEther('0.1');
const [expectedTokens, totalFee] = await curve.getBuyPrice(amountToSpend);

const minTokensOut = (expectedTokens * 95n) / 100n;

const tx = await factory.buy(tokenAddress, minTokensOut, {
	value: amountToSpend,
});

const receipt = await tx.wait();
Always get a quote before buying. Prices move based on bonding curve math, protect users with minTokensOut.

sell

Sell creator tokens back to the bonding curve.
token
address
required
Address of the token to sell
tokenAmount
uint256
required
Amount of tokens to sell
minNativeOut
uint256
required
Minimum native tokens expected (slippage protection)
Returns:
  • nativeReceived: Amount of native tokens received
Events Emitted:
  • TokenSold
Example:
const curveAddress = await factory.getCurve(tokenAddress);
const token = new ethers.Contract(tokenAddress, TOKEN_ABI, signer);

const amountToSell = ethers.parseEther('1000');
await token.approve(curveAddress, amountToSell);

const curve = new ethers.Contract(curveAddress, CURVE_ABI, provider);
const [expectedNative, totalFee] = await curve.getSellPrice(amountToSell);

const minNativeOut = (expectedNative * 95n) / 100n;

const tx = await factory.sell(tokenAddress, amountToSell, minNativeOut);
await tx.wait();

sellPercentage

Sell a percentage of your token balance, perfect for “Sell 25%” buttons.
token
address
required
Address of the token to sell
basisPoints
uint256
required
Percentage in basis points (5000 = 50%, 10000 = 100%)
minNativeOut
uint256
required
Minimum native tokens expected
Returns:
  • nativeReceived: Amount of native tokens received
Events Emitted:
  • TokenSold
Example:
const curveAddress = await factory.getCurve(tokenAddress);
await token.approve(curveAddress, ethers.MaxUint256);

const tx = await factory.sellPercentage(tokenAddress, 5000, minNativeOut);
Basis Points: 100 basis points = 1%. So 2500 = 25%, 5000 = 50%, 10000 = 100%.

Admin Functions

migrate

Graduate a bonded token to DEX. Owner-only function.
token
address
required
Address of the token to migrate
migrator
address
required
Address of the DEX migrator contract
Returns:
  • poolAddress: Address of the created liquidity pool
  • platformName: Name of the DEX platform
Events Emitted:
  • TokenMigrated
Requirements:
  • Token must be bonded (all 850M tradeable tokens sold)
  • Token must not already be graduated
  • Caller must be contract owner
  • Migrator must implement IDEXMigrator interface
Example:
const UNISWAP_MIGRATOR = '0x...';

const tx = await factory.migrate(tokenAddress, UNISWAP_MIGRATOR);
const receipt = await tx.wait();

const event = receipt.logs
	.map((log) => factory.interface.parseLog(log))
	.find((e) => e?.name === 'TokenMigrated');

console.log('LP Pool created:', event.args.poolAddress);
console.log('Platform:', event.args.platformName);
console.log('Liquidity added:', ethers.formatEther(event.args.nativeLiquidity));
For Creators: You cannot manually trigger migration. Graduation is handled by RektHub’s automated systems after your token bonds and you select your preferred DEX.

withdrawFees

Withdraw accumulated platform fees. Owner-only function. Example:
const balance = await provider.getBalance(factory.address);
console.log('Withdrawable fees:', ethers.formatEther(balance));

const tx = await factory.withdrawFees();
await tx.wait();

View Functions

getCurve

Get the bonding curve address for a token.
token
address
required
Token address
Returns:
  • address: Bonding curve address
Example:
const curveAddress = await factory.getCurve(tokenAddress);
console.log('Curve for token:', curveAddress);

const curve = new ethers.Contract(curveAddress, CURVE_ABI, provider);

getCreationFee

Get the current token creation fee. Returns:
  • uint256: Creation fee in native tokens
Example:
const fee = await factory.getCreationFee();
console.log('Creation fee:', ethers.formatEther(fee), 'ETH');

Events

TokenCreated

Emitted when a new token is deployed.
event TokenCreated(
    address indexed tokenAddress,
    address indexed curveAddress,
    address indexed creator,
    string name,
    string symbol,
    string uri,
    uint256 realNativeReserves,
    uint256 realTokenReserves,
    uint256 virtualNativeReserves,
    uint256 virtualTokenReserves,
    uint256 creationFee
);
Use Cases:
  • Track new token launches
  • Build trending token feeds
  • Creator analytics dashboards

TokenPurchased

Emitted when tokens are bought through the factory.
event TokenPurchased(
    address indexed token,
    address indexed curve,
    address indexed buyer,
    uint256 nativeIn,
    uint256 tokensOut,
    uint256 totalFee,
    uint256 creatorFee,
    uint256 platformFee,
    uint256 newRealNativeReserves,
    uint256 newRealTokenReserves,
    uint256 newVirtualNativeReserves,
    uint256 newVirtualTokenReserves
);
Use Cases:
  • Real-time trade feeds
  • Price charts and volume tracking
  • Creator earnings dashboards

TokenSold

Emitted when tokens are sold through the factory.
event TokenSold(
    address indexed token,
    address indexed curve,
    address indexed seller,
    uint256 tokensIn,
    uint256 nativeOut,
    uint256 totalFee,
    uint256 creatorFee,
    uint256 platformFee,
    uint256 newRealNativeReserves,
    uint256 newRealTokenReserves,
    uint256 newVirtualNativeReserves,
    uint256 newVirtualTokenReserves
);

TokenMigrated

Emitted when a token graduates to DEX.
event TokenMigrated(
    address indexed tokenAddress,
    address indexed curveAddress,
    address indexed poolAddress,
    string platformName,
    uint256 nativeLiquidity,
    uint256 tokenLiquidity,
    uint256 migrationFee,
    uint256 creatorFee,
    uint256 platformFee
);

FeesWithdrawn

Emitted when platform fees are withdrawn.
event FeesWithdrawn(
    address indexed recipient,
    uint256 amount
);

Integration Tips

Always Use Factory for Consistency

// ✅ Good: Use factory
await factory.buy(tokenAddress, minTokensOut, { value: amount });

// ❌ Avoid: Directly calling curve (unless you have a reason)
await curve.buy(buyer, minTokensOut, { value: amount });

Handle Events Efficiently

const tokenFilter = factory.filters.TokenPurchased(tokenAddress);
factory.on(tokenFilter, (token, curve, buyer, nativeIn, tokensOut) => {
	updateUI({ buyer, nativeIn, tokensOut });
});

factory.on('TokenPurchased', handlePurchase);
factory.on('TokenSold', handleSale);

Multi-Chain Setup

const factories = {
	1: new ethers.Contract(ETHEREUM_FACTORY, ABI, ethProvider),
	8453: new ethers.Contract(BASE_FACTORY, ABI, baseProvider),
	42161: new ethers.Contract(ARB_FACTORY, ABI, arbProvider),
};

async function buyOnChain(chainId, tokenAddress, amount) {
	const factory = factories[chainId];
	return factory.buy(tokenAddress, minOut, { value: amount });
}

Next Steps

Bonding Curve Contract

Learn about the trading engine

Token Contract

Understand creator token standards

Buying Guide

Deep dive into buying patterns

Events Reference

Complete events documentation