Welcome to Prothesis, a phased governance DAO smart contract built on Solana using Anchor. This project implements a decentralized autonomous organization (DAO) with streamlined proposal lifecycle management, council-controlled membership, and secure multisig funding approvals.
Note: Experimental features are available in the
experimentalbranch, including NFT minting for approved proposals, lazy account initialization, and DAO configuration updates via community consensus. These features are marked as experimental because they either use experimental Anchor features or have passed initial tests but not comprehensive end-to-end testing.
- Overview
- Features
- Experimental Features
- Architecture
- Installation
- Usage
- Instructions
- Account Types
- Multisig Governance
- Error Handling
- Development
- Contributing
- License
Prothesis is a Solana program implementing a DAO with a single-phase proposal system. Proposals must reach a consensus threshold (e.g., 75% upvotes) within a time limit or are dismissed automatically. Approved proposals can be funded only via multisignature transactions requiring council member approvals. Upon funding, proposals are minted as NFTs to the DAO treasury as sponsorship badges.
Membership and council privileges govern key DAO actions such as adding members, promoting council members, and funding proposals — all secured by multisig consensus to ensure decentralized control.
- Proposal Lifecycle: Submit, vote, review, resolve, and fund proposals.
- Time-bound Proposals: Proposals auto-expire after a configurable time limit.
- Unweighted, One-Vote-Per-Member Voting: Votes are unweighted and each member votes once per proposal.
- Council Membership: Only council members can add new members or promote peers.
- Multisig Funding: Proposal funding requires multisig approvals by a configurable threshold of council members.
- NFT Sponsorship: Funded proposals are minted as NFTs to the DAO treasury vault.
- Role-based Access Control: DAO membership, council, and aspirants have clear privileges enforced in program logic.
- Consensus Thresholds: Configurable percentage-based consensus thresholds for proposal approvals, council promotions, and multisig actions.
- Robust Error Handling: Descriptive custom errors to facilitate debugging and safe operation.
The following experimental features are available in the experimental branch:
-
NFT Minting for Approved Proposals: When a proposal is successfully approved and resolved, an NFT is automatically minted to commemorate the proposal. This NFT serves as a permanent record on the blockchain and can be used for historical tracking and recognition.
-
Lazy Account Initialization: To optimize compute unit usage and reduce transaction costs, accounts are now initialized lazily (only when needed). This approach significantly reduces the computational overhead of the program.
-
DAO Configuration Updates via Consensus: The DAO configuration can now be updated after deployment through a community consensus process, allowing for more flexible governance as the DAO evolves.
Note: These features are marked as experimental because they either utilize experimental features in the Anchor framework or have been developed in our program and have passed initial tests but not comprehensive end-to-end testing. Use them with caution in non-production environments.
The program uses Anchor framework patterns with strongly-typed accounts and instructions.
DaoConfig: Stores DAO-wide config including consensus thresholds, council size, treasury accounts, and bump seeds.Member: Represents DAO members, tracks council status and ownership.Proposal: Stores proposal data, voting state, status, timestamps, and treasury references.RoleOp: Tracks pending promotions, demotions, or removals of members/council with multisig votes.Treasury: PDA account holding DAO funds for proposals and other expenses.
- Initialize DAO: Set up DAO config, treasury, and admin.
- Add Member: Add new member accounts; restricted to council members.
- Promote/Demote Council Members: Initiate and resolve role operations requiring multisig consensus.
- Submit Proposal: Members create detailed proposals linked to DAO.
- Vote Proposal: Members cast unweighted up/down votes.
- Review Proposal: Any user can resolve proposal status (approve/dismiss/expire) based on votes and time.
- Fund Proposal: Council multisig approves funding; funds transfer from treasury to proposal treasury; mint NFT sponsorship.
- Exit DAO / Remove Member: Members can leave; council can remove members.
-
Rust and Cargo
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup component add rustfmt clippy rustup target add bpfel-unknown-unknown
-
Solana CLI
sh -c "$(curl -sSfL https://release.solana.com/v1.16.0/install)"Add Solana to your PATH as instructed by the installer.
-
Anchor CLI
cargo install --git https://github.com/coral-xyz/anchor avm --locked avm install latest avm use latest
-
Node.js and Yarn (for client and tests)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash nvm install 16 nvm use 16 npm install -g yarn
-
Clone the repository
git clone https://github.com/yourusername/prothesis.git cd prothesis -
Install dependencies
yarn install
-
Build the program
anchor build
-
Update Program ID After building, update the program ID in
Anchor.tomlandlib.rswith the generated program ID:solana-keygen pubkey target/deploy/prothesis-keypair.json
Then update the ID in the files mentioned above.
-
Start a local Solana validator
solana-test-validator
-
Deploy to localnet
anchor deploy
-
Run tests
anchor test
-
Configure Solana CLI for the desired network
# For devnet solana config set --url https://api.devnet.solana.com # For testnet solana config set --url https://api.testnet.solana.com # For mainnet solana config set --url https://api.mainnet-beta.solana.com
-
Create or import a keypair for deployment
solana-keygen new -o deployer.json
Or import an existing keypair.
-
Fund the deployer account (for devnet/testnet)
solana airdrop 2 $(solana-keygen pubkey deployer.json) -
Build and deploy
anchor build anchor deploy --provider.wallet deployer.json
To initialize a new DAO, you need to:
- Create a DAO configuration with appropriate thresholds
- Set up the initial council member(s)
- Initialize the treasury
Example using the Anchor client:
// Initialize DAO with configuration
await program.methods.initializeDao({
name: "My DAO",
proposalThreshold: 75, // 75% approval needed
roleOpThreshold: 60, // 60% approval for role changes
proposalDuration: 604800, // 1 week in seconds
})
.accounts({
authority: adminWallet.publicKey,
daoConfig: daoPDA,
treasury: treasuryPDA,
systemProgram: SystemProgram.programId,
})
.signers([adminWallet])
.rpc();Only council members can add new members:
await program.methods.addMember(memberWallet.publicKey, "Member Name", false)
.accounts({
authority: councilMemberWallet.publicKey,
daoConfig: daoPDA,
member: memberPDA,
systemProgram: SystemProgram.programId,
})
.signers([councilMemberWallet])
.rpc();Members can submit proposals and vote on them:
// Submit proposal
await program.methods.submitProposal(
"Proposal Title",
"Proposal Description",
new BN(1000000000) // 1 SOL funding request
)
.accounts({
authority: memberWallet.publicKey,
member: memberPDA,
daoConfig: daoPDA,
proposal: proposalPDA,
systemProgram: SystemProgram.programId,
})
.signers([memberWallet])
.rpc();
// Vote on proposal
await program.methods.voteOnProposal(true) // true for upvote
.accounts({
authority: voterWallet.publicKey,
member: voterMemberPDA,
proposal: proposalPDA,
vote: votePDA,
systemProgram: SystemProgram.programId,
})
.signers([voterWallet])
.rpc();For more detailed examples, refer to the test files in the tests/ directory.
The Prothesis development workflow follows these steps:
- Feature Planning: Define new features or improvements in issues
- Branch Creation: Create feature branches from
mainusing the naming conventionfeature/feature-name - Implementation: Develop the feature with appropriate tests
- Testing: Run comprehensive tests to ensure functionality
- Code Review: Submit a pull request for peer review
- Integration: Merge approved changes into the
mainbranch - Deployment: Deploy to testnet/devnet for further testing
- Release: Tag stable versions for mainnet deployment
prothesis/
├── Anchor.toml # Anchor configuration
├── Cargo.toml # Rust dependencies
├── programs/
│ └── prothesis/ # Main program code
│ ├── src/
│ │ ├── lib.rs # Program entry point
│ │ ├── error.rs # Custom error definitions
│ │ ├── state/ # Account structures
│ │ └── instructions/ # Program instructions
├── tests/ # Integration tests
├── migrations/ # Deployment scripts
└── app/ # Client application (if applicable)
The project employs a comprehensive testing strategy:
- Unit Tests: Test individual components in isolation
- Integration Tests: Test interactions between components
- End-to-End Tests: Test complete workflows
Tests are categorized into:
- Green Tests: Happy path scenarios
- Red Tests: Error and edge cases
Run tests with:
anchor testThe project uses GitHub Actions for CI/CD:
- Build Check: Ensures the program builds successfully
- Test Suite: Runs all tests
- Linting: Checks code quality with Clippy and Rustfmt
- Security Scan: Analyzes for potential vulnerabilities
The project follows Semantic Versioning (SemVer):
- Major: Breaking changes
- Minor: New features, non-breaking
- Patch: Bug fixes and minor improvements
We welcome contributions to Prothesis! Please follow these steps:
- Fork the repository
- Create a feature branch
- Implement your changes with tests
- Submit a pull request
Please adhere to the coding standards and include appropriate tests.
This project is licensed under the MIT License - see the LICENSE file for details.