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;
}
}