Algorand xGov Beta
This document describes the architecture of the xGov process (Beta).
Specifically, the architecture aims to solve the following main requirement:
The xGov process is a trustless voting system to manage grant proposals funding and polls for the Algorand ecosystem.
The design takes a step towards this end goal, which is a fully decentralized application relying uniquely on a front-end and the Algorand Virtual Machine (AVM).
The current design minimizes the trust model and the off-chain footprint to a few operations, carried out by a back-end controlled by the Algorand Foundation, which could be pushed on the AVM in future iterations.
It is worth noting that the residual trusted off-chain operations are fully accountable on the Algorand public Ledger.
Motivation
The old xGov process (Alpha) has shown some weaknesses concerning the incentive alignment, the gamification risks of the voting system, and low-quality proposals.
Moreover, the old grant proposal submission and funding mechanism were based on a per-quarter schedule, making the whole process slow and inflexible.
Therefore, a more robust process with a continuous stream of grant proposals, votes, and funding is desirable.
Finally, given the shift of the Algorand protocol towards consensus incentivization, the xGov (Beta) voting power will be based on active consensus participation instead of ALGO locking periods (Alpha).
Architecture Overview
The xGov Architecture consists of the following components:
| COMPONENT | IMPLEMENTATION |
|---|---|
| xGov Portal | Front-End |
| xGov Registry | Algorand Application (Factory) |
| xGov Treasury | Algorand Application Account |
| xGov Manager | Algorand Address |
| xGov Committee Manager | Algorand Address |
| xGov Daemon | Algorand Address, Back-End + DB |
| xGov Council | Algorand Address |
| xGov Payor | Algorand Address |
| xGov Subscriber | Algorand Address |
| xGov | Algorand Address + Box |
| Managed Subscriber | Algorand Address |
| xGov (Un)Subscription Request | Box |
| xGov Committee | JSON (ARC-86) |
| Proposer | Algorand Address + Box |
| KYC Provider | Algorand Address |
| Proposal | Algorand Application (Child) |
| Proposal Metadata | Box |
| Proposal Escrow | Algorand Application Account |
| Proposal Voters | Boxes |
The on-chain components are used for:
- On/off-boarding xGovs;
- Whitelisting Proposers (KYC required);
- Creating and submitting Proposals;
- Binding xGov Committees to Proposals;
- Voting on Proposals;
- Managing the xGov Treasury and funding approved Proposals.
The off-chain components are used for:
- Selecting xGov Committees periodically and verifiably, according to ARC-86;
- Intermediate Proposers’ KYC;
- Intermediate on/off-boarding of xGovs that cannot execute a self-subscription or self-unsubscription.
Reading Guidelines
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document, are to be interpreted as described in RFC 2119.
The data types (like uint64, byte[], etc.) in this document are to be interpreted
as specified in ARC-4.
📝 NOTE
Notes like this are non-normative
📎 EXAMPLE
Sections like this are examples aiming to clarify the specifications.
Sections like this are either pseudo-code or data structures.
Math Symbols
For a correct rendering of mathematical symbols and formulas, it is recommended to
right-click on the symbol below, and select Math Settings -> Math Renderer -> Common HTML from the drop-down menu.
$$ \mathcal{C} $$
Once MathJax rendering is correctly set, you should see a calligraphic “C”.
xGov Registry
The xGov Registry is the orchestrator of the xGov process. It is used to:
-
Manage the role-based access control of the process;
-
Onboard and offboard xGovs;
-
Onboard and enable Proposers (KYC required);
-
Create Proposals;
-
Bind the xGov Committees to Proposals;
-
Manage the xGov Treasury and funding approved Proposals.
The xGov Registry is implemented as an Application, deployed by the original xGov Manager.
Roles
xGov Manager
The xGov Manager is an Algorand Address controlled by the Algorand Foundation.
It represents the root of trust for the xGov process.
RBAC
The xGov Manager MAY rotate itself.
The xGov Manager MUST provide and MAY update the xGov Committee Manager Address.
The xGov Manager MUST provide and MAY update the xGov Daemon Address.
The xGov Manager MUST provide and MAY update the xGov Council Address.
The xGov Manager MUST provide and MAY update the xGov Payor.
The xGov Manager MUST provide and MAY update the xGov Subscriber Address.
The xGov Manager MUST provide and MAY update the KYC Provider Address.
Configuration and Updates
The xGov Manager MAY pause the xGov Registry.
The xGov Manager MAY pause the creation of new Proposals.
The xGov Manager MAY update the xGov Registry anytime.
The xGov Manager MAY reconfigure the parameters of the xGov Registry.
Treasury Management
The xGov Manager MAY execute withdrawals of outstanding funds from the xGov Treasury.
xGov Committee Manager
The xGov Committee Manager is an Algorand Address controlled by the Algorand Foundation.
The xGov Committee Manager SHALL declare the xGov Committee currently in charge on the xGov Registry.
xGov Daemon
The xGov Daemon is an Algorand Address controlled by the Algorand Foundation (back-end).
The xGov Daemon SHALL assign the xGov Committee currently in charge (voters and their voting power) to open Proposals.
The xGov Daemon SHOULD delete absentees (voters) after Proposals scrutiny.
xGov Council
The xGov Council is an Algorand Address representing a group of elected Councilors.
The xGov Council MUST have an odd number of Councilors.
The xGov Council MUST review approved Proposals (see Proposal review section).
The xGov Council MAY apply a veto against approved Proposals according to the terms and conditions of the xGov process.
The xGov Council majority vote is REQUIRED to apply a veto against approved proposals.
xGov Payor
The xGov Payor is an Algorand Address controlled by the Algorand Foundation.
The xGov Payor MAY disburse the requested funds for approved and reviewed Proposals if there are enough funds in the xGov Treasury.
xGov Subscriber
The xGov Subscriber is an Algorand Address controlled by the Algorand Foundation.
The xGov Subscriber MAY onboard or offboard xGovs who cannot execute a self-subscription or self-unsubscription (e.g., due to contract immutability or other restrictions).
Treasury
The xGov Treasury is an Algorand Address controlled by the xGov Registry.
Treasury Inflows
| FLOW | FROM | TO | AMOUNT | METHOD | CONDITION |
|---|---|---|---|---|---|
| Deposit Governance Funds | Anyone | xGov Treasury | Any | deposit_funds | |
| xGov Subscription | Anyone | xGov Treasury | xGov Fee | subscribe_xgov | |
| xGov Subscription Request | Anyone | xGov Treasury | xGov Fee | request_subscribe_xgov | |
| xGov Unsubscription Request | Anyone | xGov Treasury | xGov Fee | request_unsubscribe_xgov | |
| Proposer Subscription | Anyone | xGov Treasury | Proposer Fee | subscribe_proposer | |
| Open Proposal | Anyone | xGov Treasury | Open Proposal Fee | open_proposal | |
| Slash Proposal Commitment | Proposal Escrow | xGov Treasury | Proposal Locked Deposit | review (on Proposal) | Veto is applied (block=True) |
Treasury Outflows
| FLOW | FROM | TO | AMOUNT | METHOD | CONDITION |
|---|---|---|---|---|---|
| Open Proposal | xGov Treasury | Proposal Escrow | Partial Proposal Fee | open_proposal | |
| Pay Proposal | xGov Treasury | Proposer | Requested Amount | pay_grant_proposal | Proposal is approved |
| Withdraw Governance Funds | xGov Treasury | xGov Manager | Up to available Governance Funds | withdraw_funds | |
| Withdraw Outstanding Balance | xGov Treasury | xGov Manager | Outstanding balance, excluding MBR and Governance Funds | withdraw_balance |
📝 NOTE
Partial Open Proposal Fees are equal to the Open Proposal Fee discounted by the Proposal Application MBR.
Treasury MBRs
-
Treasury Application Account;
-
xGov Boxes;
-
Proposer Boxes;
-
Created Proposal Applications.
xGovs
An xGov MUST have an Algorand Address (\( a \)).
An xGov MUST provide a Voting Address.
It is RECOMMENDED to provide a Voting Address different from the xGov Address, to facilitate voting operation on behalf of the xGov Address (supposed to be secure and less accessible).
The xGov Address and the current Voting Address MAY update the Voting Address.
The xGov Address MUST subscribe on (acknowledge) the xGov Registry, to acquire the xGov status.
The xGov status is defined as the pair \( (a, h) \), where:
- \( a \) is the xGov Address;
- \( h \) is the block at which the xGov Address subscribed.
The xGov Address MAY unsubscribe from the xGov Registry, losing the xGov status.
📝 NOTE
xGov Address can be associated with any Account type. This ensures the compatibility and inclusivity of xGov participation (direct or delegated).
Subscription
The xGov Registry provides two xGov (un)subscription procedures:
-
Self-Subscription: the xGov Address MUST call the xGov Registry.
-
Managed-Subscription: the ownership of the xGov App Address is verified off-chain, by the Algorand Foundation, according to a pre-defined trust model. The Managed-Onboarding/Offboarding is executed in two steps:
-
Users issue a (Un)Subscription Request to (un)subscribe, declaring the xGov App Address, the Application Owner Address, and a Relation Type (enumerative that identifies a pre-defined trust model).
-
The Algorand Foundation verifies the declared and accountable xGov/Owner Addresses relationship off-chain (based on the Relation Type) and eventually approves it.
-
📝 NOTE
For further details about existing and new Relation Types, refer to the Relation Types section.
An xGov Fee MUST be paid to the xGov Treasury for the subscription or subscription request or unsubscription request.
📝 NOTE
The xGov Manager MAY update the xGov Fee.
The xGov Fee has the following scope:
-
Minimal deterrent for Sybil attacks;
-
Covering the xGov Box MBR (see below).
xGov Box
An xGov is associated with a Box on the xGov Registry, called xGov Box.
xGov Box ID is equal to: [X||<xgov address>], where X is a domain separation
prefix and || denotes concatenation.
An xGov Box has the following ABI schema:
{
"voting_addr": "address",
"voted_proposals": "uint64",
"last_vote_timestamp": "uint64",
"subscription_round": "uint64"
}
The xGov Fee MUST NOT be lower than the xGov Box MBR.
xGov Self-Subscription
The xGov Fee MUST be paid to the xGov Treasury upon xGov Box creation.
The xGov Fee MAY NOT be paid by the xGov Address.
The Voting Address declared on subscription MUST BE assigned to the xGov Box.
xGov Managed-Subscription
An xGov (Un)Subscription Request is associated with a Box on the xGov Registry, called xGov (Un)Subscription Request Box.
The xGov Fee MUST be paid to the xGov Treasury upon xGov (Un)Subscription Request Box creation.
The xGov Fee MAY NOT be paid by the xGov Address.
xGov (Un)Subscription Request Box ID is equal to: [<d>||<counter>], where <d>
is a domain separation prefix which is either r for subscription requests or ru
for unsubscription request, <counter> is a global counter for pending requests,
and || denotes concatenation.
An xGov (Un)Subscription Request Box has the following ABI schema:
{
"xgov_addr": "address",
"owner_addr": "address",
"relation_type": "uint64"
}
The xGov (Un)Subscription Request MUST be performed by the Owner Address.
The xGov Fee MUST NOT be lower than the xGov (Un)Subscribe Request Box MBR.
If the Algorand Foundation approves the subscription request:
-
The xGov Subscription Request Box MUST be destroyed;
-
An xGov Box MUST be created using the xGov Address declared on the subscription request.
-
The Owner Address declared on the subscription request MUST be assigned to the Voting Address in the created xGov Box.
-
The subscription round MUST be set to the current round number in the created xGov Box.
If the Algorand Foundation approves the unsubscription request:
-
The xGov Unsubscription Request Box MUST be destroyed;
-
The xGov Box of the xGov address MUST be destroyed.
Relation Types
A Relation Type identifies the trust model and the off-chain verification process of the xGov App Address ownership for a Managed-Subscription.
New Relation Type Request
A request for a new Relation Type SHALL be submitted by the Application Creator opening a new Relation Type Request issue.
A Relation Type MUST be approved by the Algorand Foundation.
Available Relation Type
The following enumerative relation_type (uint64) are currently available:
| RELATION TYPE | ENUM |
|---|---|
| Réti Pooling | 1 |
| Compx LST | 2 |
Relation Type 1: Réti Pooling
Réti Validators are created by an immutable factory contract.
A Validator is uniquely owned by an immutable Owner Address.
Each Validator may control several Staking Pools, which participate in Algorand consensus.
To request a Managed Subscription for a Réti Staking Pool:
- The
relation_typeMUST be set to1; - The
owner_addrMUST be set to the Validator Owner Address; - The
xgov_addrMUST be set to the Staking Pool Address.
Relation Type 2: Compx LST
TBD
$$ \newcommand {\abs}[1] {\lvert #1 \rvert} \newcommand \A {\mathcal{A}} \newcommand \N {\mathbb{N}} \newcommand \Comm {\mathsf{Comm}} \newcommand \Addr {\mathrm{Addr}} \newcommand \Members {\mathrm{Members}} \newcommand \Votes {\mathrm{Votes}} $$
xGov Committee
xGov Committees are responsible for voting on Proposals.
The formalization of xGov Committees and their voting power, as defined by ARC-0086, is provided below.
Preliminaries
Let
- \( \A \) be the (finite) set of Algorand addresses;
- \( \N \) be the set of non–negative integers;
- \( g \) be the network Genesis Hash;
- \( R \in \N \) be the Application ID of the xGov Registry;
- \( B_c \in \N \) be the block at which the xGov Registry was created.
Governance Period
A governance period is a pair \( (B_i, B_f) \in \N^2 \) such that
$$ \begin{align} B_i &\equiv 0 \pmod{10^6}, \\ B_f &\equiv 0 \pmod{10^6}, \\ B_f &> B_c, \\ B_f &> B_i. \end{align} $$
And is intended as a range of blocks \( [B_i; B_f) \) (\( B_i \) included, \( B_f \) excluded).
\( B_i < B_c \) is valid and denotes a period across the xGov Registry creation.
xGovs and Voting Power
An xGov is an address \( a \in \A \) that has acknowledged the xGov Registry on block \( h \) and is therefore eligible to acquire voting power.
The xGov acknowledgement is defined by the pair \( (a, h) \) (represented on the xGov Registry as an xGov Box).
If xGovs unsubscribe, the xGov acknowledgement of their address \( a \) is lost and the pair \( (a, h) \) is removed from the xGov Registry state.
For a governance period \( (B_i, B_f) \), an address \( a \) is an eligible xGov in \( [B_c; B_f) \) if and only if there exists a block height \( k \) with \( B_c ≤ k < B_f \) such that the xGov Registry state at height \( k \) contains \( (a, h) \) for some \( h ≤ k \).
Once the xGov Registry has recorded an acknowledgement \( (a, h) \) with \( h ≥ B_c \), the address \( a \) is considered an eligible xGov for every governance period \( (B_i, B_f) \) such that \( h \in [B_c; B_f) \); in particular, it is not necessary to re-acknowledge the xGov Registry for subsequent governance periods.
For a fixed governance period \( (B_i, B_f) \), the voting power of an eligible xGov \( (a, h) \) in that governance period is the integer
$$ w((a, h); B_i, B_f) \in \N, $$
defined as the number of blocks proposed by an eligible address \( a \) in the governance period \( [B_i; B_f) \)1.
If an xGov a has acknowledged the xGov Registry at some \( h \in [B_c; B_f) \) and has proposed one or more blocks in \( [B_i; B_f) \), then all such proposals in \( [B_i; B_f) \) contributes to its voting power, including those that occurred before \( h \).
Definition of xGov Committee
Fix an xGov Registry \( (g, R, B_c) \) and a governance period \( (B_i, B_f) \) as above.
An xGov Committee for \( (g, R, B_c, B_i, B_f) \) is a finite set
$$ C \subseteq \A \times \N_{>0}, $$
of address–weight pairs \( (a, v) \) such that:
$$ \begin{align} &\textbf{eligibility} && \forall (a, v) \in C, a \text{ is an eligible xGov in } [B_c; B_f), \\ &\textbf{voting power} && \forall (a, v) \in C, v = w(a; B_i, B_f), \\ &\textbf{uniqueness} && (a_1, v_1), (a_2, v_2) \in C \text{ and } a_1 = a_2 \Rightarrow v_1 = v_2. \end{align} $$
The corresponding xGov Committee object is the tuple
$$ \Comm := (g, R, B_c, B_i, B_f, C). $$
For convenience, we write
$$ \Addr(C) := \{ a \in \A \mid \exists v>0, (a, v) \in C \} $$
for the set of xGov Committee members (addresses) induced by \( C \).
xGov Committee Members
The number of xGov Committee members (or cardinality of the xGov Committee) is defined as
$$ \Members(\Comm) := \abs{\Addr(C)} = \abs{C}. $$
This value corresponds to the totalMembers field in the ARC-86 canonical JSON
representation of
the xGov Committee.
xGov Committee Voting Power
The voting power function of the xGov Committee is the map
$$ v_C : \Addr(C) \to \N_{>0}, \qquad v_C(a) := v \text{ such that } (a, v) \in C. $$
The total committee voting power is
$$ \Votes(\Comm) := \sum_{(a, v) \in C} v = \sum_{a \in \Addr(C)} v_C(a). $$
This value corresponds to the totalVotes field in the ARC-86 canonical JSON representation
of the xGov Committee.
Optionally, the relative vote of a member \( a \in \Addr(C) \) is
$$ \mathrm{share}_C(a) := \frac{v_C(a)}{\Votes(\Comm)}, $$
whenever \( \Votes(\Comm) > 0 \).
xGov Committee ID
An xGov Committee is identified by the Committee ID, as defined in ARC-86 canonical JSON representation.
Selection
The xGov Committee selection and the assignment of their voting power is performed by the Algorand Foundation.
Declaration
The xGov Committee Manager SHALL declare on the xGov Registry:
-
The current Committee ID;
-
The current xGov Committee Members;
-
The current xGov Committee Voting Power.
Assignment to Proposal
The xGov Daemon SHALL assign the current xGov Committee to Proposals upon creation (see Proposal Creation section).
-
If \( a \) is not eligible as an xGov in \( [B_c; B_f) \), its voting power is implicitly taken to be zero, and it is not included in the xGov Committee. ↩
Proposers
A Proposer MUST have an Algorand Address.
KYC
A Proposer MUST have a valid or invalid KYC status, defined by a KYC process.
The Proposer KYC status MUST have an expiration date.
The KYC Provider SHALL update the Proposer KYC status after the KYC process.
The KYC Provider MAY update the Proposer KYC during its validity.
The Proposer KYC status MUST be valid and not expired to receive Proposal funding.
Subscription
A Proposer Fee MUST be paid to the xGov Treasury for the subscription.
📝 NOTE
The xGov Manager MAY modify the Proposer Fee.
The Proposer Fee has the following scope:
-
Covering the KYC process costs;
-
Covering the Proposer Box MBR (see below).
Proposer Box
A Proposer is associated with a Box on the xGov Registry, called Proposer Box.
The Proposer Fee MUST be paid to the xGov Treasury upon creating the Proposer Box.
The Proposer SHOULD pay the Proposer Fee.
Proposer Box ID is equal to [P||<proposer address>], where P is a domain separation
prefix and || denotes concatenation.
A Proposer Box has the following ABI schema:
{
"active_proposal": "bool",
"kyc_status": "bool",
"kyc_expiring": "uint64"
}
The Proposer Fee MUST NOT be lower than the Proposer Box MBR.
Proposal
A Proposal is a funding request from the xGov Treasury, which is approved or rejected by the xGov Committee vote and reviewed by the xGov Council.
A Proposal consists of:
-
Proposal Application, with REQUIRED data;
-
Proposal metadata.
The Proposal Application is created and funded by the xGov Registry App (see Creation section) through the Open Proposal Fee.
Lifecycle
The Proposal life cycle has four phases:
Funding Types
The Proposals have two different funding types:
-
Retroactive
-
Claim: “I have done X, which has benefited the Algorand ecosystem because of Y metrics, I would like to receive Z as compensation for the work”.
-
Positive outcome: funding is immediately disbursed if the Proposal is approved by the xGov Committee vote, and the xGov Council does not apply a veto according to the terms and conditions.
-
-
Proactive (NOT AVAILABLE YET)
-
Claim: “I want to do X, it has the potential Y for the Algorand ecosystem, I would like to receive Z staggered behind these milestones”.
-
Positive outcome: funding will be disbursed if the Proposal is approved by the xGov Committee vote, after milestone reviews from the xGov Council, and if the xGov Council does not apply a veto according to terms and conditions.
-
Requested Amount
The Proposal’s requested amount (\( A \)) MUST be bounded as follows:
| Small | Medium | Large | |
|---|---|---|---|
| Requested Amount | \( A_\min ≤ A < A_{S,\max} \) | \( A_{S,\max} ≤ A < A_{M,\max} \) | \( A_{M,\max} ≤ A ≤ A_{L,\max} \) |
Funding Sizes
Proposals have different funding sizes based on the requested amount of funds.
The funding size defines the timing of the Proposal lifecycle.
| Small | Medium | Large | |
|---|---|---|---|
| Discussion time | \( D_S \) | \( D_M \) | \( D_L \) |
| Voting time (after discussion) | \( V_S \) | \( V_M \) | \( V_L \) |
📝 NOTE
Refer to the Proposal implementation configuration for the Proposal lifecycle timing values.
Quorum Thresholds
$$ \newcommand \Comm {\mathsf{Comm}} \newcommand \Members {\mathrm{Members}} \newcommand \Votes {\mathrm{Votes}} $$
Proposals have two quorum thresholds based on the requested amount of funds.
The quorum thresholds define the minimum number of (regular and weighted) votes required to approve a Proposal:
-
\( T(A) \), Democratic Quorum Threshold (
1xGov,1Vote); -
\( T_w(A) \), Weighted Quorum Threshold (
1xGov,wVotes).
Given the xGov Committee assigned to the Proposal, with its members and voting power (see the xGov Committee definition), the quorum thresholds are defined as follows:
- \( T(A) = \Members(\Comm) \times Q(A) \), with
$$ Q(A) = Q_\min + \frac{\Delta Q}{\Delta A} \times (A - A_\min) $$
- \( T_w(A) = \Votes(\Comm) \times Q_w(A) \), with
$$ Q_w(A) = Q_{w,\min} + \frac{\Delta Q_w}{\Delta A} \times (A - A_\min) $$
Where:
- \( Q_\min = Q(A_\min) \)
- \( Q_\max = Q(A_{L,\max}) \)
- \( Q_{w,\min} = Q_w(A_\min) \)
- \( Q_{w,\max} = Q_w(A_{L,\max}) \)
- \( \Delta Q = Q_\max - Q_\min \)
- \( \Delta Q_w = Q_{w,\max} - Q_{w,\min} \)
- \( \Delta A = A_{L,\max} - A_\min \)
📝 NOTE
Refer to the Proposal implementation configuration for the minimum and maximum quorum values.
Metadata
The Proposal Metadata byte length MUST NOT exceed 30 kB.
The Proposal Metadata is stored in a Box on the Proposal Application, called Metadata Box.
The Proposal Metadata Box ID is equal to metadata.
The Proposal Metadata Box body has no ABI schema (raw bytes).
Finite-State Machine
A Proposal SHALL be in one of the following enumerated statuses:
| Status | Enum | Description |
|---|---|---|
EMPTY | 0 | The xGov Registry creates an empty proposal, the Proposer SHOULD open a draft (or it SHOULD be finalized for staleness) |
DRAFT | 10 | The Proposer MAY submit (with updated metadata) or drop the draft (or it SHOULD be finalized for staleness) |
SUBMITTED | 20 | The xGov Daemon SHALL assign the xGov Committee to the submitted proposal, which is then opened to vote |
VOTING | 25 | The xGov Committee MAY vote the proposal until the voting session expires |
APPROVED | 30 | The outcome of the vote scrutiny (quorum and majority) approved the proposal, the absentees SHALL be deleted, the xGov Council SHALL review it |
REJECTED | 40 | The outcome of the vote scrutiny (quorum and majority) rejected the proposal, the absentees SHALL be deleted, it SHOULD be finalized |
REVIEWED | 45 | The xGov Council positively reviewed the approved proposal (T&C, etc.), the locked amount MUST be returned to the Proposer, the xGov Payor MAY disburse the requested amount |
BLOCKED | 60 | The xGov Council blocked the approved proposal with veto, it SHOULD be finalized, the locked amount MUST be slashed, the requested amount MUST NOT be paid |
FUNDED | 50 | The xGov Payor paid the requested amount, it SHOULD be finalized |
FINALIZED | bool | The proposal life cycle is terminated and MAY be deleted |
📝 NOTE
The
FINALIZEDboolean flag is not an enumerated state, since it can be superposed to several states (i.e.,EMPTY,DRAFT,REJECTED,BLOCKED, andFUNDED). Example: a Proposal can beFUNDEDandFINALIZED.
Escrow
The Proposal Escrow is an Address controlled by the Proposal Application.
Escrow Inflows
| FLOW | FROM | TO | AMOUNT | METHOD | CONDITION |
|---|---|---|---|---|---|
| Open Proposal | xGov Treasury | Proposal Escrow | Partial Proposal Fee | open_proposal (on xGov Registry) | |
| Deposit Proposal Commitment | Proposer | Proposal Escrow | Proposal Locked Deposit | open |
Escrow Outflows
| FLOW | FROM | TO | AMOUNT | METHOD | CONDITION |
|---|---|---|---|---|---|
| Operations Funding | Proposal Escrow | xGov Daemon | % of Open Proposal Fee | submit | |
| Return Proposal Commitment | Proposal Escrow | Proposer | Proposal Locked Deposit | drop | |
| Return Proposal Commitment | Proposal Escrow | Proposer | Proposal Locked Deposit | scrutiny | Proposal is rejected |
| Return Proposal Commitment | Proposal Escrow | Proposer | Proposal Locked Deposit | finalize | Proposal is dropped for staleness |
| Return Proposal Commitment | Proposal Escrow | Proposer | Proposal Locked Deposit | review | Veto is not applied (block=False) |
| Slash Proposal Commitment | Proposal Escrow | xGov Treasury | Proposal Locked Deposit | review | Veto is applied (block=True) |
| Claim Voters MBR | Proposal Escrow | xGov Treasury | Voters Box MBR | finalize | |
| Close Out Proposal | Proposal Escrow | xGov Treasury | Metadata Box MBR + App Account | delete |
Escrow MBRs
-
Proposal Application Account
-
Metadata Box
-
xGov Committee Voters Boxes
Creation
Proposers can create a Proposal at any time.
The Proposer MUST provide the following REQUIRED data to open a Proposal:
-
Title: a short name for the Proposal;
-
Focus: an enumerative focus area (e.g., Wallets, SDKs, etc.);
-
Funding Type: enumerative for Retroactive or Proactive (currently just Retroactive);
-
Requested Amount (in 𝜇ALGO).
A Proposer MUST NOT have more than one active proposal at any time.
The Proposer creates a Proposal Application from the xGov Registry.
Upon Proposal creation, an Open Proposal Fee MUST be paid to the xGov Treasury.
The Open Proposal Fee MUST NOT be lower than the sum of:
-
Proposal Application MBR;
-
Proposal Escrow Account MBR;
-
Full Metadata Box MBR;
-
Daemon Operations Funding.
The Proposal Application MBR is deducted from the Open Proposal Fee; the remainder MUST be entirely transferred to the Proposal Escrow.
📝 NOTE
The xGov Manager MAY update the Proposal Fee.
The remainder of the Open Proposal Fee MUST cover the MBR of all the Boxes required by the xGov Committee assigned to the Proposal upon opening.
📎 EXAMPLE
Given a Proposer Voter Box size, the Open Proposal Fee amount SHOULD be proportional to the xGov Committee size. The Voter Box MBR is roughly \( 0.02 \) ALGO. Example: an xGov Committee of \( 500 \) voters requires roughly \( 10 \) ALGO of MBR to the Proposal Application.
The Proposer SHOULD pay the Open Proposal Fee.
The Open Proposal Fee has the following scope:
-
Anti-spam measure;
-
Covering Proposal Escrow Account MBR;
-
Covering Proposal Metadata Box MBR;
-
Covering xGov Committee Boxes MBR (introduced later).
-
Covering xGov Daemon operation fees for the Proposal.
Upon opening the Proposal Draft, the Proposer MUST lock in the Proposal Escrow a percentage of the requested funding amount as a commitment.
📝 NOTE
The xGov Manager MAY update the percentage of the requested funding amount to commit.
The locked amount SHALL be either:
-
Returned to the Proposer when the Proposal is:
- Reviewed and not blocked by veto by the xGov Council or Rejected by voting;
- Dropped by the Proposer before submission.
-
Slashed if the Proposal is blocked with a veto by the xGov Council.
Upon proposal opening, the xGov Committee ID, total members, and total voting power MUST be fetched from the xGov Registry and assigned to the Proposal.
The xGov Daemon MAY finalize the Empty Proposal if it becomes stale (the Proposer does not open a Draft).
Discussion
The Proposer MAY update the Proposal Metadata during the discussion phase.
The Proposer SHALL NOT change the Proposal REQUIRED data (e.g., the requested amount) during the discussion phase.
To change the Proposal REQUIRED data, the Proposer MUST drop the Proposal Draft and open a new one.
Submission
The Proposer SHALL submit the Draft Proposal after the minimum discussion period (depending on the Proposal funding size).
The xGov Daemon MAY finalize the Draft Proposal if it becomes stale (the Proposer does not submit the Draft).
The Proposal Metadata SHOULD be submitted from the xGov Portal (front-end).
The Proposal MUST NOT be submitted without Metadata.
Upon proposal submission, a percentage of the Open Proposal Fee SHALL be transferred from the Proposal Escrow to the xGov Daemon to cover the operation fees.
📝 NOTE
The xGov Manager MAY update the percentage of the Open Proposal Fee transferred to the xGov Daemon.
Vote Distribution
$$ \newcommand \Comm {\mathsf{Comm}} \newcommand \Members {\mathrm{Members}} \newcommand \Votes {\mathrm{Votes}} $$
The xGov Daemon SHALL distribute the votes to the xGov Committee (\( \Comm \)) assigned to the Proposal.
The distributed votes MUST be equal to the xGov Committee Voting Power (\( \Votes(\Comm) \)) (see xGov Committee section).
The number of voters who received votes MUST be equal to the xGov Committee Members (\( \Members(\Comm) \)) (see xGov Committee section).
The Proposal status MUST be set to Voting once the xGov Committee is completely assigned.
Voters
The xGov Committee Voters are represented by a set of Boxes on the Proposal Application (one box per xGov Committee Member), called the Voter Box.
The xGov Daemon SHALL create all the Voter Boxes once the Proposal is Submitted.
Voter Box MBR MUST be covered by the Partial Open Proposal Fee.
Voter Box ID is equal to [V||<xgov address>], where V is a domain separation
prefix, <xgov address> is the same as used by the xGov upon subscription, and
|| denotes concatenation.
A Voter Box has the following ABI schema:
{
"votes": "unit32"
}
Vote Opening
The Submitted Proposal MUST be promoted to Voting once the xGov Committee has been completely assigned.
The duration of the voting session depends on the Proposal funding sizes.
The Voting Proposal MUST stay open until either:
-
All the xGov Committee members have voted, or
-
The voting duration expires.
Votes
xGovs vote MUST BE either “Approve”, “Reject”, or “Null”.
xGovs MAY abstain from voting.
xGovs SHALL vote once per Proposal: the allocation of “Approve”, “Reject”, and “Null” votes MUST be simultaneous.
Vote usage MAY be partial. Unused votes are default “Null”.
The sum of “Approve”, “Reject”, and “Null” votes of each xGov MUST equal to the xGov voting power.
Vote SHALL NOT be modified.
📎 EXAMPLE
Pooled Vote Example: Let’s have an xGov Staking Pool with
Nvotes. The Pool SHOULD collect poolers’ opinions before expressing the Pool vote accordingly. Once the Pool is ready to vote, the allocation ofNvotes among “Approve”, “Reject”, or “Null” is simultaneous and can no longer be modified.
Scrutiny
A Submitted Proposal is Approved if and only if all the following conditions hold:
-
A democratic quorum of all xGov Committee (one xGov, one vote) is reached. “Null” votes affect this quorum.
-
A weighted quorum of all xGov Committee voting power is reached. “Null” votes affect this quorum.
-
The relative majority of “Approve” over “Reject” votes is reached. “Null” votes do not affect the relative majority.
And it is Rejected otherwise.
The Commitment Lock MUST be returned to the Proposer if the Proposal is Rejected.
The xGov Daemon SHALL delete Voter Boxes of absentees xGovs.
Review
All Voter Box MUST be deleted before reviewing the Proposal.
The xGov Council MUST review Approved Proposals.
The xGov Council MAY apply a veto to an Approved Proposal.
An Approved Proposal is considered either:
-
Blocked, if the veto is applied;
-
Reviewed, if the veto is not applied.
In case of a Blocked Proposal:
-
The requested amount MUST NOT be paid.
-
The Commitment Lock MUST be transferred (slashed) from the Proposal Escrow to the xGov Treasury.
In case of a Reviewed Proposal:
- The Commitment Lock MUST be returned from the Proposal Escrow to the Proposer.
Finalization
Payment
The xGov Payor MAY pay a Reviewed Proposal and promote it to Funded.
If the Proposal is Funded:
- The requested amount MUST BE transferred from the xGov Treasury to its Proposer.
Finalize
The xGov Daemon SHOULD finalize:
-
Empty and Draft Proposals, after a stale period,
-
Funded, Rejected, or Blocked Proposals.
If a Draft Proposal is finalized, the Commitment Lock MUST be returned to the Proposer.
Outstanding balance of the Proposal Escrow MUST be returned to the xGov Treasury.
Delete
The xGov Manager MAY delete Finalized Proposals.
The Proposal Metadata MUST be deleted before deletion (Empty Proposals are an exception).
Proposal Escrow MUST be closed to the xGov Treasury before deletion.
Events
The xGov Architecture provides the following classes of ARC-28 events:
-
xGov Registry Events, emitted by the xGov Registry singleton application.
-
Proposal Events, emitted by the Proposal applications.
Clients can subscribe to these ARC-28 events using the AlgoKit Subscriber Library.
xGov Registry Events
XGovSubscribed
An xGov subscribed (either through self-onboarding or managed onboarding).
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| xGov | address | The address of the subscribed xGov |
| Delegate | address | The address of the delegated voter |
XGovUnsubscribed
An xGov unsubscribed (either through self-onboarding or managed onboarding).
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| xGov | address | The address of the unsubscribed xGov |
ProposerSubscribed
A Proposer subscribed.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Proposer | address | The address of the subscribed Proposer |
ProposerKYC
A Proposer KYC status update.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Proposer | address | The address of the unsubscribed Proposer |
| Valid KYC | bool | The Proposer KYC is valid |
NewCommittee
A new xGov Committee has been elected.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Committee ID | byte[32] | ARC-86 Committee ID |
| Size | uint32 | Committee members |
| Votes | uint32 | Committee votes |
NewProposal
A new Proposal has been opened.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Proposal ID | uint64 | Proposal Application ID |
| Proposer | address | Proposer address |
Proposal Events
Opened
The Proposal has been opened.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Funding Type | uint8 | Enum: Retroactive (10), Proactive (20) |
| Requested Amount | uint64 | Requested Amount (microALGO) |
| Category | uint8 | Small (10), Medium (20), Large (30) |
Submitted
The Proposal has been submitted for voting.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Vote Opening | uint64 | Vote Opening UNIX timestamp |
| Vote Closing | uint64 | Vote Closing UNIX timestamp |
| Quorum Voters | uint32 | Democratic Quorum (voters) required to pass |
| Weighted Quorum Votes | uint32 | Weighted Quorum (votes) required to pass |
Vote
A vote has been cast on the Proposal.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| xGov | address | xGov address that expressed the vote |
| Total Voters | uint32 | Voters so far |
| Total Approvals | uint32 | Approval votes so far |
| Total Rejections | uint32 | Rejections votes so far |
| Total Nulls | uint32 | Null votes so far |
Scrutiny
The vote has been scrutinized.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Approved | bool | The Proposal has been approved (both quorums reached and majority approved) |
| Plebiscite | bool | All Committee members voted |
Review
The xGov Council has reviewed the Proposal.
| ARGUMENT | TYPE | DESCRIPTION |
|---|---|---|
| Veto | bool | The proposal has been blocked with a veto |
Numeric Precisions
Percentages
All the percentages MUST have a precision of two decimals and be expressed as
basis-points (bps) scaled as Algorand
Virtual Machine (AVM) uint64.
📎 EXAMPLE
The AVM works with
uint64, therefore \( 100.00 \% = 10{,}000 \mathrm{bps} \). So, \( 12.5 \% \) of \( X \) is calculated on the AVM as:$$ \frac{1{,}250 \mathrm{bps} \times X}{10{,}000 \mathrm{bps}}. $$
Testing
xGov Architecture uses the PyTest framework for unit tests and end-to-end tests.
PyTest fixtures are organized hierarchically in the tests folder: fixtures defined
in the conftest.py file at higher levels are available to all the nested-level
tests.
Configuration
| PARAMETER | CLIENT VALUE | CLIENT UNIT | AVM VALUE | AVM UNIT |
|---|---|---|---|---|
| xGov Fee | \( 10 \) | ALGO | \( 10 \times 10^6 \) | 𝜇ALGO |
| Proposer Fee | \( 100 \) | ALGO | \( 100 \times 10^6 \) | 𝜇ALGO |
| Open Proposal Fee | \( 100 \) | ALGO | \( 100 \times 10^6 \) | 𝜇ALGO |
| Daemon Operation Funding | \( 5 \) | % of Open Proposal Fee | \( 500 \) | bps |
| Proposal Commitment | \( 3 \) | % of Requested Amount | \( 300 \) | bps |
| Minimum Requested Amount | \( 2{,}500 \) | ALGO | \( 2{,}500 \times 10^6 \) | 𝜇ALGO |
| Maximum Requested Amount Small | \( 25{,}000 \) | ALGO | \( 25{,}000 \times 10^6 \) | 𝜇ALGO |
| Maximum Requested Amount Medium | \( 100{,}000 \) | ALGO | \( 100{,}000 \times 10^6 \) | 𝜇ALGO |
| Maximum Requested Amount Large | \( 200{,}000 \) | ALGO | \( 200{,}000 \times 10^6 \) | 𝜇ALGO |
| Discussion duration Small | \( 3 \) | Week | \( 1{,}814{,}400 \) | seconds |
| Discussion duration Medium | \( 3 \) | Week | \( 1{,}814{,}400 \) | seconds |
| Discussion duration Large | \( 3 \) | Week | \( 1{,}814{,}400 \) | seconds |
| Voting duration Small | \( 1 \) | Week | \( 604{,}800 \) | seconds |
| Voting duration Medium | \( 1 \) | Week | \( 604{,}800 \) | seconds |
| Voting duration Large | \( 2 \) | Week | \( 1{,}209{,}600 \) | seconds |
| Quorum Min | \( 30 \) | % | \( 3{,}000 \) | bps |
| Quorum Max | \( 70 \) | % | \( 7{,}000 \) | bps |
| Weighted Quorum Min | \( 50 \) | % | \( 5{,}000 \) | bps |
| Weighted Quorum Max | \( 70 \) | % | \( 7{,}000 \) | bps |
Deployment
xGov Registry
| Network | xGov Registry |
|---|---|
| Main Net | 3147789458 |
| Test Net | 742949200 |
xGov Council
App Specs
xGov Architecture Integrations
The xGov Architecture supports integrations with external on-chain Applications, especially those related to vote delegation of xGovs or the vote of the xGov Council.
Third parties and Applications can rely on the xGov Registry ARC-56 App Spec to build:
-
The App Client for direct ABI calls to the xGov Registry, or
-
The App Interface for internal C2C ABI calls to the xGov Registry from their Applications.
To integrate the xGov Registry, you can follow these steps:
-
Download the xGov Registry ARC-56 App Spec or add the
xgov-beta-scas git submodule to your project. -
Use the
algokit generate client ...to call the xGov Registry with a direct ABI call using the App Client. -
Use the
puyapy-clientgenutility to call the xGov Registry with an innerabi_call()using the App Interface.
CI/CD
Branch Management
---
title: Trunk-based with CD
---
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main'}} }%%
gitGraph
commit tag: "0.37.0"
branch "feat/add-foo-123"
branch "feat/add-bar-123"
checkout "feat/add-foo-123"
commit id: "feat(foo): ..."
commit id: "doc(foo): ..."
checkout main
merge "feat/add-foo-123" tag: "v1.0.0.canary.1"
branch "feat/add-baz-123"
commit id: "feat(baz): ..."
commit id: "doc(baz): ..."
commit id: "test(baz): ..."
checkout "feat/add-bar-123"
commit id: "chore(bar): ..."
commit id: "feat(bar): ..."
checkout main
merge "feat/add-bar-123" tag: "v1.0.0.canary.2"
checkout main
branch "version/1.0.0"
commit id: "bump(v1.0.0): pyproject.toml"
checkout main
branch release
merge "version/1.0.0"
commit id: "release(v1.0.0): ..." tag: "v1.0.0"
checkout main
merge release
checkout main
merge "feat/add-baz-123" tag: "v1.1.0.canary.1"
Protected Branches
main(default), the trunkrelease
The trunk is considered stable and MUST:
- Reject commits not included in a Pull Request
- Require Docs and TestNet deployments to be healthy to accept commits from
release - Meet the quality criteria defined in the CI/CD pipeline
The release branch MUST:
- Be kept in sync with
main - Be used to generate release tags
- Reject commits from branches other than
mainthat are:- Not included in a Pull Request
- Have a
diffthat is not strictly equal to thepyproject.tomlversion bump.
The CI/CD pipeline ensures that:
-
The
mainbranch contains release-grade code at any time (both for Smart Contracts and Docs) -
The
releasebranch is synced withmainand used only to generate release tags (reflected aspyproject.tomlversion)
Unprotected Branches
Features, major refactoring, dependency bumps, or bugfixes SHALL be carried out
on a dedicated unprotected branch pointing to the trunk (main).
The pyproject.toml release version bumps SHALL be carried out on a dedicated
unprotected branch pointing to the release branch.
Draft Pull Requests from unprotected branches, either to main or release, SHOULD
skip the CI.
Deployments
The CD makes use of the following deployment environments:
-
github-pages: to host the static documentation (mdBook) -
contract-testnet: to continuously deploy Smart Contracts to the Algorand TestNet -
contract-mainnet: to deploy Smart Contracts to the Algorand MainNet on release
Implementation
The CI/CD pipeline is implemented with the following automated workflows:
-
Smart Contracts CI (tests, lint, output stability, mock deployment)
-
Smart Contracts CD (to TestNet)
-
Documentation CI (tests, lint)
-
Documentation CD (to GitHub Pages)
-
Release CI (validate release tag, version, etc.)
-
Release (to MainNet)
And the following manually dispatchable workflows:
- xGov Registry parameters configuration
- xGov Registry RBAC management
- Pause and Resume Proposals
- Release and Update xGov Council
Contribution Guidelines
The xGov Architecture source code is released on the official GitHub repository.
Issues can be submitted on the GitHub issues page.
External contributions to tests and documentation are welcome. If you would like to contribute, please read these guidelines and consider submitting a Pull Request.
⚠️ Commits must be signed!
Docs Guidelines
By clicking on the “Suggest an edit” icon in the top-right corner, while reading this book, you will be redirected to the relevant documentation source code file to be referenced in an Issue or edited in a Pull Request.
The xGov Architecture Specifications book is built with mdBook.
The book is written in CommonMark.
The CI pipeline enforces Markdown linting, formatting, and style checking with
markdownlint.
Numbered Lists
Numbered lists MUST be defined with 1-only style.
📎 EXAMPLE
1. First item 1. Second item 1. Third itemResult:
- First item
- Second item
- Third item
Tables
Table rows MUST use the same column widths.
📎 EXAMPLE
✅ Correct table format
| Month | Savings | |----------|---------| | January | €250 | | February | €80 | | March | €420 |❌ Wrong table format
| Month | Savings | |----------|---------| | January | €250 | | February | €80 | | March | €420 |Result:
Month Savings January €250 February €80 March €420
Consider aligning text in the columns to the left, right, or center by adding a
colon : to the left, right, or on both sides of the dashes --- within the header
row.
📎 EXAMPLE
| Name | Quantity | Size | |:-------|:--------:|-----:| | Item A | 1 | S | | Item B | 5 | M | | Item C | 10 | XL |Result:
Name Quantity Size Item A 1 S Item B 5 M Item C 10 XL
MathJax
Mathematical formulas are defined with MathJax.
mdBook MathJax documentation.
Block Styles
Block styles are defined in the ./docs/_include/styles.md file using the mdBook
include feature.
Block styles (e.g., examples, implementation notes, etc.) are “styled quote” blocks included in the book.
📎 EXAMPLE
This example block has been included with the following syntax:
{{#include ./_include/styles.md:example}} > This example block has been included with the following syntax:
Bug Bounty
Refer to the GitHub repository security policy.
License
Refer to the GitHub repository license.