Governance and Proposal Process
Overview
This guide shows you how to participate in protocol governance as a sequencer. You'll learn how to signal support for protocol upgrades, create proposals, and vote on governance decisions that shape the Aztec network.
Prerequisites
Before proceeding, you should:
- Have a running sequencer node (see Sequencer Setup Guide)
- Have a basic understanding of Aztec's governance model and voting mechanisms
Understanding Governance Components
Payloads
Protocol upgrades consist of a series of commands that execute on protocol contracts or replace contract references. You define these steps in a contract called a payload that you deploy on Ethereum.
This guide assumes the payload already exists at a known address. You'll participate in the payload's journey through signaling, proposal creation, voting, and execution.
Before signaling support or voting, always:
- Verify the payload address on Etherscan or your preferred block explorer
- Review the
getActions()function to understand what changes the payload will make - Check if the payload has been audited (if applicable)
- Discuss the proposal with the community on Aztec Discord
Never signal or vote for a payload you haven't personally verified.
Here's an example payload structure:
contract UpgradePayload is IPayload {
IRegistry public immutable REGISTRY;
address public NEW_ROLLUP = address(new FakeRollup());
constructor(IRegistry _registry) {
REGISTRY = _registry;
}
function getActions() external view override(IPayload) returns (IPayload.Action[] memory) {
IPayload.Action[] memory res = new IPayload.Action[](1);
res[0] = Action({
target: address(REGISTRY),
data: abi.encodeWithSelector(REGISTRY.addRollup.selector, NEW_ROLLUP)
});
return res;
}
function getURI() external pure override(IPayload) returns (string memory) {
return "UpgradePayload";
}
}
If this payload's proposal passes governance voting, the governance contract executes addRollup on the Registry contract.
Contract Addresses
Key contracts you'll use:
- Governance Proposer: Handles payload signaling and proposal creation
- Governance Staking Escrow (GSE): Manages stake delegation and voting
- Governance: Executes approved proposals
- Rollup: Your sequencer stakes here and defaults to delegating voting power here
To obtain these contract addresses: Check your sequencer logs at startup for the line beginning with INFO: node Aztec Node started on chain...
Governance Lifecycle Overview
The governance process follows these stages:
- Signaling: Sequencers signal support for a payload when proposing blocks. A payload needs a quorum of support to be promoted to a proposal. Signaling can start any time from the moment a payload is deployed.
- Proposal Creation: After reaching quorum, anyone can submit the payload as an official proposal.
- Voting Delay (12 hours): A mandatory waiting period before voting opens (allows time for community review).
- Voting Period (24 hours): Users who hold stake in the network vote on the proposal using their staked tokens.
- Execution Delay (12 hours): After passing the vote, another mandatory delay before execution (allows time for node upgrades).
- Execution: Anyone can execute the proposal, which applies the changes.
Note: These timeline values are specific to testnet and are subject to change for future network phases.
Signaling Support for a Payload
As a sequencer, you initiate proposals through signaling. When you propose a block, you can automatically signal support for a specific payload. Once enough sequencers signal support within a round, the payload qualifies to become an official proposal.
How Signaling Works
- Only you can signal during slots when you're the block proposer
- Your sequencer node automatically calls
signalon theGovernanceProposercontract when proposing a block (if you've configured a payload address) - Rounds consist of 300 slots each (180 minutes at 36 seconds per slot). At every 300-block boundary, the system checks if any payload has received 151 or more signals (the quorum threshold, which is >50% of the round size)
- Payloads that reach quorum can be submitted as official proposals by anyone
Note: Round size and quorum threshold will change between testnet and ignition. These values and any further references to these values are relevant for testnet only.
Configure Your Signaling Preference
Use the setConfig method on your node's admin interface to specify which payload address you want to signal support for.
Call the JSON-RPC interface:
curl -X POST http://localhost:8880 \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc":"2.0",
"method":"nodeAdmin_setConfig",
"params":[{"governanceProposerPayload":"0x1234567890abcdef1234567890abcdef12345678"}],
"id":1
}'
Replace 0x1234567890abcdef1234567890abcdef12345678 with your actual payload contract address.
Expected response:
{"jsonrpc":"2.0","id":1}
Verify Your Configuration
Use the getConfig method to verify the payload address:
curl -X POST http://localhost:8880 \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc":"2.0",
"method":"nodeAdmin_getConfig",
"id":1
}'
Search for governanceProposerPayload in the response to confirm it matches your configured address.
Once configured, your sequencer automatically signals support for this payload each time you propose a block. Each signal counts toward the quorum requirement.
Creating a Proposal
Once a payload receives the required quorum (151 signals in a 300-slot round), you or any user can call submitRoundWinner on the GovernanceProposer contract to officially create the proposal.
Submit the Payload
cast send [GOVERNANCE_PROPOSER_ADDRESS] \
"submitRoundWinner(uint256)" [ROUND_NUMBER] \
--rpc-url [YOUR_RPC_URL] \
--private-key [YOUR_PRIVATE_KEY]
To find the current round number:
# Get the current round from the GovernanceProposer contract
cast call [GOVERNANCE_PROPOSER_ADDRESS] \
"getCurrentRound()" \
--rpc-url [YOUR_RPC_URL]
Verify the Created Proposal
After creation, you can query the proposal in the governance contract:
# Get the total proposal count
cast call [GOVERNANCE_CONTRACT_ADDRESS] \
"proposalCount()" \
--rpc-url [YOUR_RPC_URL]
# Query the latest proposal (count - 1, since proposals are zero-indexed)
cast call [GOVERNANCE_CONTRACT_ADDRESS] \
"proposals(uint256)" $((PROPOSAL_COUNT - 1)) \
--rpc-url [YOUR_RPC_URL]
This returns the CompressedProposal struct data, which includes:
- The payload address
- Creation timestamp
- Voting start and end times
- Current vote tallies