Governance Options
This guide explains how to configure different governance options when creating tokens with the Doppler V3 SDK, including using the NoOpGovernanceFactory for gas-efficient deployments.
Overview
The Doppler V3 SDK supports optional governance with the following models.
"Standard" Governance - Full on-chain governance with timelock using OpenZeppelin Governor
"No-Op" Governance - Minimal governance for gas savings (sets governance to
0xdead)
Using NoOpGovernanceFactory
The NoOpGovernanceFactory creates tokens without active governance, significantly reducing deployment costs and complexity. This is ideal for projects that don't require on-chain governance.
Prerequisites
Ensure the NoOpGovernanceFactory is deployed on your target chain. Currently available on:
Base Sepolia:
0x916B8987E4aD325C10d58ED8Dc2036a6FF5EB228
Implementation
import { ReadWriteFactory, CreateV3PoolParams } from 'doppler-v3-sdk';
import { DOPPLER_V3_ADDRESSES } from 'doppler-v3-sdk';
// Get addresses for your chain
const chainId = 84532; // Base Sepolia
const addresses = DOPPLER_V3_ADDRESSES[chainId];
// Check if NoOpGovernanceFactory is available
if (!addresses.noOpGovernanceFactory) {
throw new Error('NoOpGovernanceFactory not deployed on this chain');
}
// Create parameters with NoOpGovernanceFactory
const createParams: CreateV3PoolParams = {
integrator: '0x...', // Your integrator address
userAddress: '0x...', // User creating the token
numeraire: '0x...', // Base token (e.g., WETH)
contracts: {
tokenFactory: addresses.tokenFactory,
// Use NoOpGovernanceFactory instead of standard governanceFactory
governanceFactory: addresses.noOpGovernanceFactory,
v3Initializer: addresses.v3Initializer,
liquidityMigrator: addresses.liquidityMigrator,
},
tokenConfig: {
name: 'My Token',
symbol: 'MTK',
tokenURI: 'https://example.com/metadata.json',
},
vestingConfig: 'default',
// Optional: Configure V4 migration
liquidityMigratorData: '0x...', // See V4 migrator docs
};
// Create the factory instance
const factory = new ReadWriteFactory(addresses.airlock, driftClient);
// Encode and create the token
const createData = await factory.encodeCreateData(createParams);Using Standard Governance
For tokens that require governance functionality:
const createParams: CreateV3PoolParams = {
// ... other parameters ...
contracts: {
tokenFactory: addresses.tokenFactory,
// Use standard governanceFactory
governanceFactory: addresses.governanceFactory,
v3Initializer: addresses.v3Initializer,
liquidityMigrator: addresses.liquidityMigrator,
},
// Optional: Customize governance parameters
governanceConfig: {
initialVotingDelay: 3600, // 1 hour
initialVotingPeriod: 172800, // 48 hours
initialProposalThreshold: 1000000n, // 1% of supply
},
};Custom Governance Factory
To use a custom governance factory (must be whitelisted):
const createParams: CreateV3PoolParams = {
// ... other parameters ...
contracts: {
tokenFactory: addresses.tokenFactory,
// Use your custom governance factory address
governanceFactory: '0xYourCustomGovernanceFactory',
v3Initializer: addresses.v3Initializer,
liquidityMigrator: addresses.liquidityMigrator,
},
};Fee Distribution
Standard Governance (90/10 Split)
90% of liquidity → Timelock (controlled by governance)
10% of liquidity → StreamableFeesLocker (distributed to beneficiaries)
No-Op Governance (100% Locked)
For permanent liquidity provision, set the recipient to DEAD_ADDRESS:
import { DEAD_ADDRESS } from "doppler-v3-sdk";
// In no-op governance, all liquidity goes to the locker
const recipient = DEAD_ADDRESS; // 0x000...dEaDSee Also
V4 Migrator Guide - Configure V4 migration with beneficiaries
Token Launch Examples - Complete examples
Contract Addresses - Deployment addresses by chain
Last updated