Skip to main content

Simple DAO Smart Contract Template

1. Introduction

The SimpleDAO smart contract is designed to facilitate decentralized autonomous organization (DAO) operations on the AElf blockchain. It allows users to create proposals, vote on them, and withdraw tokens from voted ballots. The contract manages proposals and tracks voting status to ensure transparent and democratic decision-making within the DAO.

2. Setting up

Prerequisite:
Install aelf Contract Templates to continue.

To spin up the SimpleDAO smart contract template project, use the following command:

Terminal
dotnet new aelf-simple-dao -n $DAO_NAME

3. Understanding Project Structure

SimpleDAO Project Structure
src/

├── Protobuf/ # Protobuf definitions
│ ├── contract/
│ │ ├── simple_dao.proto # Protobuf file for SimpleDAO contract
│ ├── message/
│ │ ├── authority_info.proto # Protobuf file for authority information messages
│ ├── reference/
│ │ ├── acs12.proto # Protobuf file for ACS12 reference
│ │ ├── token_contract.proto # Protobuf file for token contract reference

├── ContractReference.cs # State referencing contracts
├── SimpleDAO.cs # Main C# file for SimpleDAO smart contract implementation
├── SimpleDAO_Helper.cs # Helper functions for SimpleDAO
├── SimpleDAOState.cs # State management for SimpleDAO, all States goes here
├── SimpleDAO.csproj # csproj

test/ # Test project for SimpleDAO

├── Protobuf/ # Protobuf definitions for tests
│ ├── message/
│ │ ├── authority_info.proto # Protobuf file for authority information messages (for testing)
│ ├── reference/
│ │ ├── acs12.proto # Protobuf file for ACS12 reference (for testing)
│ ├── stub/
│ │ ├── simple_dao.proto # Protobuf file for SimpleDAO contract (stub for testing)
│ │ ├── token_contract.proto # Protobuf file for token contract reference (stub for testing)

├── _Setup.cs # Setup script for tests
├── SimpleDAOTests.cs # Main unit test file for SimpleDAO
├── SimpleDAO.Tests.csproj # csproj

4. Understanding Interfaces

Initialize

Initializes the DAO and sets the token symbol for the DAO members.

public override Empty Initialize(InitializeInput input)
  • Parameters:
    • InitializeInput input: Contains the token symbol to be used by the DAO.
  • Returns: Empty
  • Assertions:
    • The contract should not be already initialized.
    • The token contract address must be retrievable.
    • The token symbol provided should exist.

CreateProposal

Creates a new proposal in the DAO.

public override Empty CreateProposal(CreateProposalInput input)
  • Parameters:
    • CreateProposalInput input: Contains details of the proposal such as title, description, start time, and end time.
  • Returns: Empty
  • Assertions:
    • Title and description should not be empty.
    • Start time should be greater than or equal to the current block time.
    • End time should be greater than the current block time.

Vote

Allows members to vote on a proposal.

public override Empty Vote(VoteInput input)
  • Parameters:
    • VoteInput input: Contains proposal ID and vote details.
  • Returns: Empty
  • Assertions:
    • Proposal must exist.
    • Voting should be within the proposal's timeframe.
    • Voter should not have already voted on the proposal.

Withdraw

Allows members to withdraw their vote from a proposal after it has ended.

public override Empty Withdraw(WithdrawInput input)
  • Parameters:
    • WithdrawInput input: Contains proposal ID.
  • Returns: Empty
  • Assertions:
    • Proposal must exist.
    • Proposal should have ended.

GetAllProposals

Returns a list of all proposals in the DAO.

public override ProposalList GetAllProposals(Empty input)
  • Parameters:
    • Empty input
  • Returns: ProposalList

GetProposal

Returns details of a specific proposal.

public override Proposal GetProposal(StringValue input)
  • Parameters:
    • StringValue input: Contains the proposal ID.
  • Returns: Proposal
  • Assertions:
    • Proposal must exist.

HasVoted

Checks if a specific address has voted on a proposal.

public override BoolValue HasVoted(HasVotedInput input)
  • Parameters:
    • HasVotedInput input: Contains proposal ID and address.
  • Returns: BoolValue

GetTokenSymbol

Returns the token symbol used by the DAO.

public override StringValue GetTokenSymbol(Empty input)
  • Parameters:
    • Empty input
  • Returns: StringValue

5. Preparing for deployment

5.1 Creating A Wallet

To send transactions on the aelf blockchain, you must have a wallet.

Run this command to create aelf wallet.

Terminal
aelf-command create

result

5.2 Acquiring Testnet Tokens for Development

To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens.

Get ELF Tokens

Run the following command to get testnet ELF tokens from faucet. Remember to either export your wallet address or replace $WALLET_ADDRESS with your wallet address.

Terminal
curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d ""

To check your wallet's current ELF balance:

Terminal
aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance

You will be prompted for the following:
Enter the required param <symbol>: ELF
Enter the required param <owner>: $WALLET_ADDRESS

You should see the Result displaying your wallet's ELF balance.

5.3 Building your Smart Contract

Build the code with the following commands:

Terminal
cd src
dotnet build

6. Deploying Your Smart Contract

The smart contract needs to be deployed on the chain before users can interact with it.

Run the following command to deploy a contract.

Terminal
aelf-deploy -a $WALLET_ADDRESS -p $WALLET_PASSWORD -c $CONTRACT_PATH/$CONTRACT_FILE.dll.patched -e https://tdvw-test-node.aelf.io/

Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address.

result