Profit-Splitting DAO Vault

What it does:
A smart contract vault that collects profits and automatically splits them among DAO members based on predefined ownership or governance-approved shares.

Why it matters:
DAOs often struggle with fair, transparent profit distribution. This contract removes discretion and politics by enforcing deterministic, on-chain profit splitting that anyone can audit.

How it works:

  • DAO members and their profit shares are registered on-chain.

  • Profits are sent directly to the DAO vault.

  • Funds are allocated proportionally to each member.

  • Members can withdraw their earned profits at any time.

  • All allocations and withdrawals are transparently recorded.

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

/**
 * @title ProfitSplittingDAOVault
 * @author Nam
 * @notice DAO vault that splits profits among members proportionally
 */
contract ProfitSplittingDAOVault {

    // -------------------- DATA STRUCTURES --------------------

    struct Member {
        uint256 share;    // Profit share weight
        uint256 balance;  // Withdrawable profit
        bool active;
    }

    mapping(address => Member) public members;
    address[] public memberList;

    address public dao;
    uint256 public totalShares;

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

    event MemberAdded(address indexed member, uint256 share);
    event MemberUpdated(address indexed member, uint256 newShare);
    event ProfitReceived(uint256 amount);
    event ProfitAllocated(uint256 amount);
    event Withdrawn(address indexed member, uint256 amount);

    // -------------------- MODIFIERS --------------------

    modifier onlyDAO() {
        require(msg.sender == dao, "Not DAO");
        _;
    }

    modifier onlyMember() {
        require(members[msg.sender].active, "Not member");
        _;
    }

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

    constructor(address _dao) {
        require(_dao != address(0), "Invalid DAO");
        dao = _dao;
    }

    // -------------------- DAO GOVERNANCE --------------------

    /**
     * @notice Add a DAO member
     */
    function addMember(address _member, uint256 _share)
        external
        onlyDAO
    {
        require(_member != address(0), "Invalid address");
        require(_share > 0, "Invalid share");
        require(!members[_member].active, "Already member");

        members[_member] = Member({
            share: _share,
            balance: 0,
            active: true
        });

        memberList.push(_member);
        totalShares += _share;

        emit MemberAdded(_member, _share);
    }

    /**
     * @notice Update member share
     */
    function updateMemberShare(address _member, uint256 _newShare)
        external
        onlyDAO
    {
        require(members[_member].active, "Not member");
        require(_newShare > 0, "Invalid share");

        totalShares = totalShares - members[_member].share + _newShare;
        members[_member].share = _newShare;

        emit MemberUpdated(_member, _newShare);
    }

    // -------------------- PROFIT HANDLING --------------------

    /**
     * @notice Receive DAO profits
     */
    receive() external payable {
        require(msg.value > 0, "No profit received");
        emit ProfitReceived(msg.value);
        _allocateProfit(msg.value);
    }

    /**
     * @notice Allocate profits to members
     */
    function _allocateProfit(uint256 _amount) internal {
        for (uint256 i = 0; i  0, "Nothing to withdraw");

        members[msg.sender].balance = 0;
        payable(msg.sender).transfer(amount);

        emit Withdrawn(msg.sender, amount);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    /**
     * @notice Get DAO member info
     */
    function getMember(address _member)
        external
        view
        returns (
            uint256 share,
            uint256 balance,
            bool active
        )
    {
        Member memory m = members[_member];
        return (
            m.share,
            m.balance,
            m.active
        );
    }

    /**
     * @notice Get total DAO members
     */
    function memberCount() external view returns (uint256) {
        return memberList.length;
    }
}