Skip to main content

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_VOTES standard (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