Last week, we introduced Gitopia DAOs - a protocol-level solution for decentralized governance in open source projects. Today, we’ll dive deep into the technical architecture that powers these DAOs, exploring how we leverage the Cosmos SDK’s group module to enable secure, transparent decision-making from pull request approvals to treasury management.
If you haven’t read our Introduction to Gitopia DAOs, we recommend starting there for context on why we built this system and the problems it solves. This post focuses on the technical implementation details, showing how each component works together to enable true decentralized project governance.
Every action in a Gitopia DAO starts with a proposal, whether you’re merging code changes or allocating treasury funds. To understand how Gitopia implements decentralized governance, we’ll first examine how these proposals work, then dive into the technical components that power the entire system.
Understanding the Proposal Lifecycle
A successful DAO depends on its ability to make collective decisions. In Gitopia, each proposal moves through distinct phases, progressing from initial creation through member voting to final execution, with specific requirements and actions at each step. Understanding this process is crucial for both developers building on Gitopia and community members participating in governance.
The diagram above shows the complete lifecycle of a proposal in Gitopia DAOs. Let’s explore each stage in detail:
1. Proposal Creation
Gitopia seamlessly integrates governance into your daily development workflow by automatically triggering proposals during routine actions. For instance, imagine Alice tries to merge an important bug fix pull request - instead of the merge happening immediately, Gitopia creates a proposal that includes the PR details and code changes. Similarly, when Bob attempts to create a v2.0 release with major feature updates, or Carol tries to add Dave as a new repository collaborator, these actions automatically initiate governance proposals.
If your DAO settings require governance approval for these actions, Gitopia handles everything behind the scenes:
- An on-chain proposal is created automatically (e.g., “Merge PR #123: Fix memory leak in core module”)
- The voting period begins immediately
This means developers can work naturally in their preferred workflow - Gitopia quietly transforms these everyday actions into governed decisions without requiring manual proposal creation or extra steps. When Alice clicks “Merge”, she’ll see the proposal status and can track its progress through the voting period, all while the codebase remains protected by the DAO’s governance rules. Once a proposal is created, members can vote through the DAO dashboard.
2. Voting Period
During this phase, DAO members review and vote on proposals based on their assigned voting weights. For example, if a core maintainer with 100 voting power votes “YES” on a pull request merge, their vote carries more weight than a community member with 10 voting power.
Members have four distinct voting options, each serving a specific purpose:
-
YES: Indicates full support for the proposal. For example, when voting on a pull request merge, a “YES” vote means the member has reviewed the code changes and approves them.
-
NO: Expresses opposition to the proposal in its current form. For instance, a member might vote “NO” on adding a new collaborator if they believe more community discussion is needed first.
-
ABSTAIN: Allows members to acknowledge the proposal while stepping back from the decision. This is particularly useful when a member has a conflict of interest (like voting on their own pull request) or lacks the expertise to evaluate the proposal properly. Abstain votes are simply treated as no’s.
-
VETO: Represents strong opposition that may require proposal revision or abandonment. Veto votes are simply treated as no’s.
As votes come in, Gitopia:
- Calculates weighted totals (e.g., two YES votes of 50 weight each = 100 total YES weight)
- Displays real-time progress toward quorum
- Shows a breakdown of how each member voted for full transparency
3. Execution
Once the voting period concludes, the proposal enters its execution phase. Let’s walk through a real-world example:
Suppose a proposal to create a new release requires:
- 51% quorum (at least 51% of total voting power must vote YES)
- 48-hour voting period
The proposal’s execution follows these steps:
1. Expiration Check: First, Gitopia verifies the proposal hasn’t expired (still within 48 hours)
2. Quorum Calculation: Checks if enough YES votes were received. If your DAO has 1000 total voting power:
- You need at least 510 voting power worth of YES votes
- VETO and ABSTAIN votes are treated the same as NO votes
- Only YES votes count toward reaching quorum
For example:
Total Voting Power: 1000
Quorum Required: 51% (510 weighted votes)
Scenario 1 - Proposal Passes:
- YES votes: 600 weight
- NO votes: 200 weight
- ABSTAIN: 100 weight
- VETO: 100 weight
Result: PASSED (600 > 510 quorum requirement)
Scenario 2 - Proposal Fails:
- YES votes: 400 weight
- NO votes: 300 weight
- ABSTAIN: 200 weight
- VETO: 100 weight
Result: FAILED (400 < 510 quorum requirement)
3. Action Execution: If quorum is met:
- The new release can be created by executing the proposal
- The proposal executor result is updated to “Success”
4. Failed Proposals: If requirements aren’t met (expired or insufficient YES votes):
- The proposal is marked as “Failed”
- The create release proposal would need to be proposed again
This governance structure ensures that every significant action that the community or the DAO wants to protect can now go thorugh this process instead of one click individual action. While VETO and ABSTAIN votes are counted the same as NO votes, they allow members to express different levels of opposition or recusal for transparency purposes.
Implementation Deep Dive
Now that we understand how proposals flow through the system, let’s explore how Gitopia implements this governance structure using the Cosmos SDK’s group module.
The diagram above shows how Gitopia DAOs are built on top of Cosmos SDK x/group
module [1]. Each component plays a specific role:
1. Group: A collection of members with assigned voting weights that defines who can participate in governance
2. Decision Policy: Rules that determine how voting power translates into decisions (e.g., 51% threshold, voting period)
3. Group Policy: An account associated with a group and decision policy that can execute transactions when proposals pass
4. Module Account: A specialized blockchain account that acts as the DAO’s treasury, controlled programmatically by governance decisions
Gitopia simplifies DAO creation by handling the complex setup of governance components behind the scenes. While you only need to specify members, voting rules, and basic settings, the system automatically configures these essential components:
Let’s see how these pieces work together to enable our proposal lifecycle.
1. Group and Group Policy Initialization
When you create a new Gitopia DAO, the message handler internally calls group module’s CreateGroupWithPolicy
which creates a new group and group policy.
The initialization process:
1. Create a group with initial members and their voting weights
Group module stores member weights in the following format. The weights are non-negative decimal numbers and voting power is calculated relative to the total weight of the group.
message Member {
string address = 1; // Member's wallet address
string weight = 2; // Voting weight
string metadata = 3; // Optional member metadata
}
2. Set up a percentage decision policy with specified Voting period and Quorum
Here, we configure the initial voting period and quorum for proposals. This can always be changed later via Update Governance Paramater proposal.
policy := group.NewPercentageDecisionPolicy(
msg.Percentage,
votingPeriod,
time.Duration(0),
)
err = groupMsg.SetDecisionPolicy(policy)
if err != nil {
return nil, err
}
3. Creates a group policy account that can execute passed proposals
CreateGroupWithPolicy
abstracts the creation of group, group policy and setting the group policy address as the group admin. Only group policy account has the permissions to execute accepted proposals. The group members are allowed to execute passed proposals via authorization [2] granted during group creation or new member addition.
// create group and group policy account
res, err := k.groupKeeper.CreateGroupWithPolicy(ctx, groupMsg)
if err != nil {
return nil, err
}
4. Save the reference to the group in gitopia DAO object
And finally, save the reference to the created group.
// CreateDao initialized a Gitopia DAO with it's associated group and decision policy
func (k msgServer) CreateDao(goCtx context.Context, msg *types.MsgCreateDao) (*types.MsgCreateDaoResponse, error) {
...
// create group and group policy
// save reference to the group
var dao = types.Dao{
...
GroupId: res.GroupId,
Config: *msg.Config,
}
...
}
Source: msg_server_dao.go
2. Repository-Specific Governance
What makes Gitopia DAO unique is how we extend standard group governance with repository-specific actions. Each DAO can configure which actions require governance approval:
message DaoConfig {
bool require_pull_request_proposal = 1;
bool require_repository_deletion_proposal = 2;
bool require_collaborator_proposal = 3;
bool require_release_proposal = 4;
}
When these settings are enabled, attempting these actions automatically triggers the proposal lifecycle we explored earlier.
Attempting to bypass the governance will result in failure. We have added checks for dao config in messages.
func (k msgServer) InvokeMergePullRequest(goCtx context.Context, msg *types.MsgInvokeMergePullRequest) (*types.MsgInvokeMergePullRequestResponse, error) {
...
// check if repository is owned by a DAO
if baseRepository.Owner.Type == types.OwnerType_DAO {
// check if dao requires a proposal to merge pull request
if dao.Config.RequirePullRequestProposal {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("can't merge pull request without proposal"))
}
}
...
}
You should only use the message specifically defined for DAOs. The gitopia.com interface chooses the appropriate message based on DAO config.
// InvokeDaoMergePullRequest is the message which should be sent as a dao proposal
// for merging Pull Request
func (k msgServer) InvokeDaoMergePullRequest(goCtx context.Context, msg *types.MsgInvokeDaoMergePullRequest) (*types.MsgInvokeDaoMergePullRequestResponse, error) {
...
// check if the message admin and the group admin are the same
err := k.doAuthenticated(ctx, dao.GroupId, msg.Admin)
if err != nil {
return nil, err
}
...
}
Source: msg_server_pullRequest.go
3. DAO Treasury
Managing project funds securely is crucial for decentralized organizations. Gitopia solves this through a specialized module account for each DAO.
Key features:
- Account controlled by DAOs, not by individuals
- All fund transfer transactions require passed treasury spend governance proposals
- Secure custody and management of all the cross-chain assets (IBC) [3]
The DAO module account address is generated determistically using the combination of dao
prefix and dao id
.
// NewDaoAddress generates the module account address for a dao
func NewDaoAddress(daoId uint64) sdk.AccAddress {
key := append([]byte("dao"), sdk.Uint64ToBigEndian(daoId)...)
return address.Module(types.ModuleName, key)
}
And here’s the message used to transfer funds from DAO treasury module account. This can only be executed via treasury spend proposal.
// DaoTreasurySpend is the message which should be sent as a dao proposal
// for transfering funds from DAO treasury address
func (k msgServer) DaoTreasurySpend(goCtx context.Context, msg *types.MsgDaoTreasurySpend) (*types.MsgDaoTreasurySpendResponse, error) {
...
// check if the message admin and the group admin are the same
// Check if the dao treasury has enough balance
// Send coins from dao treasury to recipient
err = k.bankKeeper.SendCoins(ctx, daoAddr, recipientAddr, msg.Amount)
...
}
Source: msg_server_dao.go
Governance Versioning
A key feature of x/group
module is its proposal protection through versioning. The group module tracks changes to decision policies through a version number that increments automatically when Decision policy parameters (Voting period and Quorum) are updated.
When these changes occur:
- All existing proposals in the voting period are marked as
PROPOSAL_STATUS_ABORTED
- No further votes can be cast on aborted proposals
- Aborted proposals cannot be executed, even if they previously had sufficient votes
- New proposals must be created under the updated group policy
This versioning mechanism ensures proposals operate under consistent rules from creation to execution, preventing confusion and potential governance issues.
Future Enhancements
We would love to get your feedback or ideas after trying out Gitopia DAO. It would really help us to prioritize the improvements. Below are some of the improvements we have in our mind for improving the DAO user experience.
1. Governance Analytics
We’ll improve the governance dashboard to show essential metrics about your DAO:
Participation Metrics
- Members who voted in last 30 days: 45/50
- Average voter turnout: 85%
- Most active voters: @alice, @bob, @carol
Proposal Metrics
- Success rate: 80% of proposals pass
- Average time to decision: 36 hours
- Most common proposal types: Pull requests (60%)
This data helps you understand how your DAO operates and where to improve governance settings.
2. Improved Proposal Templates
Currently, creating proposals requires manual entry of all details without any standardized format. We will introduce structured templates for common scenarios, such as technical specification reviews.
Benefits:
- Captures all essential information in a consistent format
- Streamlines the review process
- Establishes a standard structure for technical discussions
- Minimizes clarifying questions during review
Each enhancement focuses on making DAO governance more accessible while maintaining decentralized decision-making. These features will roll out gradually over the next few releases.
Conclusion
Gitopia’s DAO implementation combines battle-tested Cosmos SDK modules with repository-specific governance features. This creates a secure, flexible framework for open-source project management that can scale from small teams to large communities.
By starting with a clear proposal lifecycle and building governance tools around it, we’ve created a system that feels natural to developers while providing the security and transparency benefits of on-chain governance.
References
[3] Inter-Blockchain Communication protocol
About Gitopia
Gitopia is a code collaboration protocol that transforms how open source communities build and maintain software. By combining decentralized governance with built-in treasury management, we enable projects to be truly community-owned and sustainable. Our mission is to create an ecosystem where open source development is both collaborative and sustainable, ensuring critical software infrastructure can thrive for the long term.
Connect With Us
Website: https://gitopia.com/
Telegram: https://t.me/Gitopia
Discord: https://discord.com/invite/mVpQVW3vKE
Twitter: https://twitter.com/gitopiaDAO