DAO Constitution Contract

What it does:
Defines the fundamental rules, governance structure, and operational procedures of a DAO in a transparent and immutable way.

Why it matters:
Ensures clarity on member rights, decision-making processes, proposal approvals, and dispute resolution, reducing ambiguity and conflicts in DAO operations.

How it works:

  • DAO founders define a constitution including voting rules, quorum, and member rights

  • Constitution text and metadata are stored on-chain for immutability

  • Smart contract enforces core governance rules like proposal submission and voting eligibility

  • Amendments can be proposed and approved through on-chain voting

  • Members’ roles and privileges are managed according to the constitution

  • Public access to the constitution ensures accountability and transparency

  • Integration with treasury, proposals, and other DAO modules is enabled

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title DAOConstitution
 * @author Nam
 * @notice On-chain constitution and governance framework for a DAO
 */
contract DAOConstitution is Ownable {

    string public constitutionURI; // IPFS/Arweave link to full constitution
    uint256 public amendmentCount;

    struct Amendment {
        string description;
        string amendmentURI;
        uint256 votesFor;
        uint256 votesAgainst;
        bool executed;
    }

    mapping(uint256 => Amendment) public amendments;
    mapping(address => uint256) public votingPower;
    mapping(address => mapping(uint256 => bool)) public hasVoted;

    // -------------------- EVENTS --------------------

    event ConstitutionUpdated(string constitutionURI);
    event AmendmentProposed(uint256 indexed amendmentId, string description);
    event Voted(uint256 indexed amendmentId, address voter, bool support);
    event AmendmentExecuted(uint256 indexed amendmentId);

    // -------------------- CONSTRUCTOR --------------------

    constructor(string memory _constitutionURI) {
        constitutionURI = _constitutionURI;
    }

    // -------------------- VOTING POWER MANAGEMENT --------------------

    function setVotingPower(address _member, uint256 _power) external onlyOwner {
        votingPower[_member] = _power;
    }

    // -------------------- AMENDMENTS --------------------

    function proposeAmendment(string calldata _description, string calldata _amendmentURI) external {
        amendmentCount += 1;
        amendments[amendmentCount] = Amendment({
            description: _description,
            amendmentURI: _amendmentURI,
            votesFor: 0,
            votesAgainst: 0,
            executed: false
        });

        emit AmendmentProposed(amendmentCount, _description);
    }

    // -------------------- VOTING --------------------

    function voteOnAmendment(uint256 _amendmentId, bool _support) external {
        require(votingPower[msg.sender] > 0, "No voting power");
        require(!hasVoted[msg.sender][_amendmentId], "Already voted");

        Amendment storage a = amendments[_amendmentId];
        require(!a.executed, "Already executed");

        if (_support) {
            a.votesFor += votingPower[msg.sender];
        } else {
            a.votesAgainst += votingPower[msg.sender];
        }

        hasVoted[msg.sender][_amendmentId] = true;

        emit Voted(_amendmentId, msg.sender, _support);
    }

    // -------------------- EXECUTION --------------------

    function executeAmendment(uint256 _amendmentId) external {
        Amendment storage a = amendments[_amendmentId];
        require(!a.executed, "Already executed");
        require(a.votesFor > a.votesAgainst, "Not approved");

        a.executed = true;
        constitutionURI = a.amendmentURI;

        emit AmendmentExecuted(_amendmentId);
        emit ConstitutionUpdated(a.amendmentURI);
    }
}