Skip to main content

Governance Actions

Governance actions are each defined by a unique Proposal<T> type. Proposals adjust protocol parameters, pause or unpause operations, or perform sensitive operations like package upgrades. Only members of the current Hashi committee can create proposals. Each proposal type has its own threshold, which a quorum of validators must reach by voting in support of the proposal. Creating a proposal casts the creator's vote. Quorum is counted against the committee in office when the proposal executes, so votes from members who left at a reconfiguration no longer count. A proposal expires seven days after it is created; it can then no longer be voted on or executed, and anyone can delete it. Executed proposals stay onchain.

The following is the current set of available proposal types.

Upgrade​

Authorizes a package upgrade and records whether it is exclusive. An exclusive upgrade atomically disables all previous versions as the new package is committed; a non-exclusive upgrade deliberately leaves them callable. Every upgrade must make this classification explicitly. See Move Package Upgrades for the decision criteria and validator rollout contract.

EnableVersion​

Re-enables a previously disabled package version, allowing the protocol to use it again.

DisableVersion​

Disables a package version, preventing it from being used. A version cannot disable itself: executing the proposal through package version N refuses to disable N (EDisableCurrentVersion). To disable a broken new version, execute through an older version that is still enabled.

UpdateConfig​

Updates existing parameters in the instant config by key; the new values apply when the proposal executes. Every entry is validated when the proposal is created and again when it executes, and the whole proposal aborts if any entry fails: the key must already exist in the store with a value of the same type (EInvalidConfigEntry), and the key must be governable. The guardian BTC public key and the Bitcoin chain id are pinned for the deployment's lifetime and cannot be written through any config proposal (EProtectedConfigKey). Values themselves are otherwise not bounded onchain: a proposal needs a supermajority of committee weight, and reviewing the proposed value is part of voting. See Configuration for the keys and defaults.

The guardian's URLs are changed through this proposal as well, with entries that set guardian_url (the public endpoint) or guardian_node_url (the endpoint nodes call) to a new string value. The URLs are the only guardian settings governance can change: the guardian's BTC public key is immutable once set, because rotating it would invalidate derived deposit addresses. Executing the proposal changes the onchain value, but a running node keeps the guardian client it already resolved from guardian_node_url, so each node must be restarted before it calls a new node URL. Nodes do not read guardian_url.

UpdateEpochConfig​

Updates existing parameters in the epoch config by key, including the MPC parameters, which must pass their range check (EInvalidConfigEntry). At execution, mpc_weight_reduction_allowed_delta must also end up below mpc_max_faulty_in_basis_points (EInconsistentMpcConfig). The new values are copied onto the next committee formed after execution; the active committee keeps its pinned copy. The pinned keys are refused here as well.

AddConfig​

Introduces new keys into the instant or epoch config, which is how a node-side setting becomes governable without a package upgrade. The proposal is insert-only: a key already present in the target store aborts, and the first value fixes the key's type for later updates. The pinned key names cannot be introduced into either store.

IgnoreMember​

Flags a registered member as ignored, or clears the flag. The next committee formed leaves an ignored member out, so its weight drops out of every threshold from then on; the current committee is never altered, and if a reconfiguration is already pending the change lands one epoch later. The member stays registered (an ignored member cannot be removed as inactive), and the same proposal type with the flag cleared re-admits it.

EmergencyPause​

Pauses or unpauses the bridge by setting the paused config flag. While paused, the chain refuses new deposit and withdrawal requests and every committee step that processes them; users can still cancel withdrawal requests, and reconfiguration and governance keep running. The two directions use different vote thresholds: pausing is deliberately cheap (governance_emergency_pause_threshold_bps, default 5% of committee weight) so a small fraction of the committee can quickly halt the system, while unpausing requires a supermajority (governance_emergency_unpause_threshold_bps, default two thirds). paused is also an ordinary config key, so an UpdateConfig proposal can set or clear it at the two-thirds threshold.

Aborting a stuck reconfiguration is deliberately not a proposal: the committees that could vote on one are the parties a stalled reconfiguration puts in doubt. It is a permissionless entry function gated on onchain state instead; see Abort Reconfig. Holding off the replacement that would otherwise follow is an UpdateConfig setting reconfig_hold, passed by the committee that is still in service.