On-Chain Governance
Deploy a Governor + Timelock governance system that lets token holders create proposals, vote, and execute on-chain actions.
Prerequisites
- An ERC-20 token with
ERC20_VOTESstandard (required for vote delegation)
1. Deploy a Governance Token
const token = await urblock.tokens.create({
name: "DAO Token",
symbol: "DAO",
standard: "ERC20_VOTES",
network: "polygon_amoy",
initial_supply: "1000000000000000000000000", // 1M tokens
features: { mintable: true },
idempotency_key: "dao-token-001",
});
2. Deploy Governor + Timelock
const gov = await urblock.governance.create({
name: "My DAO",
token_id: token.id,
network: "polygon_amoy",
voting_delay: 1, // blocks before voting starts
voting_period: 50400, // blocks (~1 week on Polygon)
quorum_numerator: 4, // 4% quorum
proposal_threshold: "1000000000000000000", // 1 token to propose
timelock_delay: 86400, // 1 day timelock
idempotency_key: "gov-001",
});
3. Delegate Voting Power
Token holders must delegate to themselves or another address to activate voting power:
await urblock.governance.delegate(gov.id, {
delegator: "0xTokenHolder...",
delegatee: "0xVoter...",
idempotency_key: "delegate-001",
});
4. Create a Proposal
const proposal = await urblock.governance.createProposal(gov.id, {
targets: ["0xTokenContract..."],
values: ["0"],
calldatas: ["0x40c10f19..."], // encoded mint call
description: "Mint 1000 tokens to the community treasury",
proposer: "0xProposer...",
idempotency_key: "proposal-001",
});
5. Vote
await urblock.governance.castVote(gov.id, proposal.id, {
voter: "0xVoter...",
support: 1, // 0 = Against, 1 = For, 2 = Abstain
idempotency_key: "vote-001",
});
6. Queue for Timelock
After voting succeeds:
await urblock.governance.queueProposal(gov.id, proposal.id, {
idempotency_key: "queue-001",
});
7. Execute
After the timelock delay passes:
await urblock.governance.executeProposal(gov.id, proposal.id, {
idempotency_key: "execute-001",
});
Query Governance State
Get Configuration
const config = await urblock.governance.getConfig(gov.id);
console.log(config.voting_delay);
console.log(config.voting_period);
console.log(config.quorum_numerator);
Check Voting Power
const power = await urblock.governance.getVotingPower(gov.id, {
address: "0xVoter...",
block_number: "12345678",
});
console.log(power.votes);
Get Proposal State
const state = await urblock.governance.getProposalState(gov.id, proposal.id);
console.log(state.state); // Pending, Active, Succeeded, Queued, Executed, etc.
Next Steps
- API: Governance — full governance endpoint reference
- SDK: Governance — all SDK methods
- Roles — manage contract roles
- Multisig Wallets — alternative multi-party control
- Token Standards — why ERC20_VOTES is required