Skip to content

Participate in Governance

This tutorial explains how to participate in ACDC on-chain governance, including viewing proposals, voting, and creating your own proposals.

Overview

ACDC uses on-chain governance for protocol decisions:

  • Proposals: Suggested changes to the protocol
  • Voting: Token holders vote based on stake
  • Execution: Approved proposals are automatically executed

Voting Power

Your voting power equals your staked ACDC: - 1 staked ACDC = 1 vote - Delegated stake counts for the validator, not the delegator - Votes can be: Yes, No, or Abstain

Proposal Types

Type Description Threshold
Parameter Change protocol parameters 50% + 1
Upgrade Protocol upgrades 66.7%
Spend Treasury spending 50% + 1
Emergency Critical fixes 75%

Viewing Proposals

Using CLI

# List active proposals
acdc governance list

# Output:
# Active Proposals:
#   #42 - Increase Block Gas Limit
#        Status: Active | Ends: 2024-01-20
#        For: 45.2% | Against: 12.1% | Abstain: 5.3%
#
#   #43 - Add New Validator Rewards
#        Status: Active | Ends: 2024-01-22
#        For: 62.8% | Against: 8.4% | Abstain: 3.1%

# View proposal details
acdc governance show 42

# Output:
# Proposal #42: Increase Block Gas Limit
# ========================================
# Proposer: dx1proposer123...
# Type: Parameter
# Status: Active
# Voting Period: 2024-01-15 to 2024-01-20
#
# Description:
# This proposal increases the block gas limit from 30M to 50M
# to accommodate higher transaction throughput.
#
# Actions:
# - setParameter("blockGasLimit", 50000000)
#
# Votes:
# For:     45,234,567 ACDC (45.2%)
# Against: 12,123,456 ACDC (12.1%)
# Abstain:  5,345,678 ACDC (5.3%)
# Quorum:  37.6% of 50% required

# List all proposals (including past)
acdc governance list --all

# Filter by status
acdc governance list --status passed
acdc governance list --status rejected

Using TypeScript SDK

import { AcdcClient, Governance } from '@acdc/sdk';

async function viewProposals() {
  const client = new AcdcClient({
    chain: 'delta',
    network: 'mainnet'
  });

  const governance = new Governance(client);

  // Get active proposals
  const active = await governance.getProposals({ status: 'active' });

  console.log('Active Proposals:');
  for (const proposal of active) {
    console.log(`\n#${proposal.id}: ${proposal.title}`);
    console.log(`  Status: ${proposal.status}`);
    console.log(`  Ends: ${new Date(proposal.endTime * 1000).toISOString()}`);
    console.log(`  For: ${proposal.votesFor.percentage}%`);
    console.log(`  Against: ${proposal.votesAgainst.percentage}%`);
  }

  // Get specific proposal
  const proposal = await governance.getProposal(42);
  console.log('\nProposal Details:');
  console.log('Title:', proposal.title);
  console.log('Description:', proposal.description);
  console.log('Proposer:', proposal.proposer);
  console.log('Actions:', proposal.actions);
}

viewProposals().catch(console.error);

Voting on Proposals

Prerequisites

  1. Have staked ACDC tokens
  2. Not have voted on this proposal yet
  3. Proposal must be in active voting period

Using CLI

# Vote yes
acdc governance vote 42 yes

# Output:
# Voting YES on Proposal #42...
# Transaction: 0xabc123...
# Vote submitted successfully!
# Your voting power: 10,000 ACDC

# Vote no
acdc governance vote 42 no

# Vote abstain (counts toward quorum but not for/against)
acdc governance vote 42 abstain

Using TypeScript SDK

import { AcdcClient, Wallet, Governance } from '@acdc/sdk';

async function vote() {
  const client = new AcdcClient({
    chain: 'delta',
    network: 'mainnet'
  });

  const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!);
  const signer = wallet.connect(client);

  const governance = new Governance(signer);

  // Check voting power
  const power = await governance.getVotingPower(wallet.address);
  console.log(`Your voting power: ${power.formatted} ACDC`);

  if (power.raw === 0n) {
    console.log('You need to stake ACDC to vote');
    return;
  }

  // Check if already voted
  const hasVoted = await governance.hasVoted(42, wallet.address);
  if (hasVoted) {
    console.log('You have already voted on this proposal');
    return;
  }

  // Cast vote
  console.log('Voting YES on proposal #42...');
  const tx = await governance.vote(42, 'yes');

  console.log('Transaction:', tx.hash);
  await tx.wait();

  console.log('Vote submitted successfully!');
}

vote().catch(console.error);

Creating Proposals

Requirements

  • Minimum 100,000 staked ACDC (proposal threshold)
  • Proposal deposit: 10,000 ACDC (returned if passed, slashed if rejected)

Using CLI

# Create parameter change proposal
acdc governance propose \
  --type parameter \
  --title "Increase Block Gas Limit" \
  --description "Increase gas limit from 30M to 50M for higher throughput" \
  --action "setParameter blockGasLimit 50000000"

# Create treasury spend proposal
acdc governance propose \
  --type spend \
  --title "Fund Development Grant" \
  --description "Allocate 100,000 ACDC for ecosystem development" \
  --action "transfer dx1recipient... 100000000000000000000000"

# Output:
# Creating proposal...
# Deposit: 10,000 ACDC
# Transaction: 0xdef456...
# Proposal created!
# Proposal ID: 44
# Voting starts: 2024-01-15
# Voting ends: 2024-01-22

Using TypeScript SDK

import { AcdcClient, Wallet, Governance, parseUnits } from '@acdc/sdk';

async function createProposal() {
  const client = new AcdcClient({
    chain: 'delta',
    network: 'mainnet'
  });

  const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!);
  const signer = wallet.connect(client);

  const governance = new Governance(signer);

  // Check if eligible to propose
  const power = await governance.getVotingPower(wallet.address);
  const threshold = await governance.getProposalThreshold();

  if (power.raw < threshold.raw) {
    console.log(`Need ${threshold.formatted} staked ACDC to propose`);
    console.log(`You have: ${power.formatted} staked ACDC`);
    return;
  }

  // Create proposal
  const proposal = {
    title: 'Increase Block Gas Limit',
    description: `
      ## Summary
      This proposal increases the block gas limit from 30M to 50M.

      ## Motivation
      Current gas limit restricts throughput during peak usage.

      ## Specification
      Set blockGasLimit parameter to 50,000,000.

      ## Risk Assessment
      Low risk - similar limits work well on other networks.
    `,
    type: 'parameter',
    actions: [
      {
        target: 'dx1paramcontract...',
        function: 'setParameter',
        args: ['blockGasLimit', 50000000]
      }
    ]
  };

  console.log('Creating proposal...');
  console.log('Deposit required: 10,000 ACDC');

  const tx = await governance.propose(proposal);
  console.log('Transaction:', tx.hash);

  const receipt = await tx.wait();

  // Get proposal ID from event
  const event = receipt.events.find(e => e.event === 'ProposalCreated');
  const proposalId = event.args.proposalId;

  console.log(`Proposal created! ID: ${proposalId}`);
}

createProposal().catch(console.error);

Delegation

Delegate your voting power to another address:

Using CLI

# Delegate to an address
acdc governance delegate dx1delegate...

# Check your delegate
acdc governance delegate --show

# Remove delegation (self-delegate)
acdc governance delegate --self

Using TypeScript SDK

// Delegate voting power
const tx = await governance.delegate('dx1delegate...');
await tx.wait();

// Check current delegate
const delegate = await governance.getDelegate(wallet.address);
console.log('Delegated to:', delegate);

// Self-delegate (remove delegation)
const selfTx = await governance.delegate(wallet.address);
await selfTx.wait();

Monitoring Governance

Subscribe to Events

// Subscribe to new proposals
governance.on('ProposalCreated', (id, proposer, title) => {
  console.log(`New proposal #${id}: ${title}`);
  console.log(`Proposer: ${proposer}`);
});

// Subscribe to votes
governance.on('VoteCast', (proposalId, voter, vote, weight) => {
  console.log(`Vote on #${proposalId}: ${vote}`);
  console.log(`Voter: ${voter}, Weight: ${weight}`);
});

// Subscribe to proposal state changes
governance.on('ProposalExecuted', (id) => {
  console.log(`Proposal #${id} executed!`);
});

governance.on('ProposalCanceled', (id) => {
  console.log(`Proposal #${id} canceled`);
});

Query Historical Data

// Get vote history for an address
const votes = await governance.getVoteHistory(wallet.address);

for (const vote of votes) {
  console.log(`Proposal #${vote.proposalId}: ${vote.vote}`);
  console.log(`  Weight: ${vote.weight}`);
  console.log(`  Time: ${new Date(vote.timestamp * 1000)}`);
}

// Get proposals by proposer
const myProposals = await governance.getProposals({
  proposer: wallet.address
});

Governance Parameters

View current governance settings:

acdc governance params

# Output:
# Governance Parameters:
#   Proposal Threshold: 100,000 ACDC
#   Proposal Deposit: 10,000 ACDC
#   Voting Period: 7 days
#   Quorum: 50%
#   Pass Threshold: 50% + 1
#   Upgrade Threshold: 66.7%
#   Emergency Threshold: 75%
#   Timelock Delay: 2 days

Complete Voting Script

// governance-voter.ts
import { AcdcClient, Wallet, Governance, formatUnits } from '@acdc/sdk';

async function main() {
  const client = new AcdcClient({
    chain: 'delta',
    network: process.env.NETWORK || 'mainnet'
  });

  const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!);
  const signer = wallet.connect(client);
  const governance = new Governance(signer);

  console.log('ACDC Governance Voter');
  console.log('=====================');
  console.log('Address:', wallet.address);

  // Check voting power
  const power = await governance.getVotingPower(wallet.address);
  console.log(`Voting Power: ${power.formatted} ACDC`);

  if (power.raw === 0n) {
    console.log('\nNo voting power. Stake ACDC to participate.');
    return;
  }

  // Get active proposals
  const proposals = await governance.getProposals({ status: 'active' });

  if (proposals.length === 0) {
    console.log('\nNo active proposals.');
    return;
  }

  console.log('\nActive Proposals:');
  for (const p of proposals) {
    const hasVoted = await governance.hasVoted(p.id, wallet.address);

    console.log(`\n#${p.id}: ${p.title}`);
    console.log(`  Type: ${p.type}`);
    console.log(`  Ends: ${new Date(p.endTime * 1000).toLocaleDateString()}`);
    console.log(`  For: ${p.votesFor.percentage}%`);
    console.log(`  Against: ${p.votesAgainst.percentage}%`);
    console.log(`  Your vote: ${hasVoted ? 'Already voted' : 'Not yet voted'}`);
  }

  // Vote on first unvoted proposal
  const proposalId = process.env.PROPOSAL_ID;
  const voteChoice = process.env.VOTE; // 'yes', 'no', or 'abstain'

  if (proposalId && voteChoice) {
    const hasVoted = await governance.hasVoted(
      parseInt(proposalId),
      wallet.address
    );

    if (hasVoted) {
      console.log(`\nAlready voted on proposal #${proposalId}`);
      return;
    }

    console.log(`\nVoting ${voteChoice.toUpperCase()} on proposal #${proposalId}...`);

    const tx = await governance.vote(
      parseInt(proposalId),
      voteChoice as 'yes' | 'no' | 'abstain'
    );

    console.log('Transaction:', tx.hash);
    await tx.wait();

    console.log('Vote submitted successfully!');
  }
}

main().catch(console.error);

Run:

MNEMONIC="your mnemonic" \
PROPOSAL_ID=42 \
VOTE=yes \
npx ts-node governance-voter.ts

Best Practices

  1. Research Before Voting
  2. Read the full proposal description
  3. Understand the technical implications
  4. Check community discussion

  5. Consider Delegation

  6. If you lack time to research, delegate to someone you trust
  7. You can always override delegation by voting directly

  8. Participate Regularly

  9. Governance requires active participation
  10. Low turnout can lead to poor decisions

  11. Proposal Quality

  12. Write clear, detailed proposals
  13. Include risk assessments
  14. Engage with community feedback

Next Steps