Community-Owned Media DAO

What it does:
Enables a community to collectively own, fund, govern, and monetize a media platform using on-chain governance and transparent revenue distribution.

Why it matters:
Breaks the centralized media model, aligns creators and audiences economically, enables censorship-resistant publishing, and ensures revenue and decision-making power belong to the community.

How it works:

  • Community members join by holding governance tokens or NFTs

  • Members propose and vote on editorial decisions, funding allocations, and platform rules

  • Treasury collects revenue from ads, subscriptions, licensing, or sponsorships

  • Smart contracts distribute revenue to contributors, editors, and the DAO treasury

  • Voting power and payouts are enforced on-chain via transparent rules

  • Contributors are rewarded based on participation, content impact, or DAO-defined metrics

  • DAO governance can evolve via on-chain proposals and upgrades

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

/**
 * @title CommunityOwnedMediaDAO
 * @author Nam
 * @notice Community-owned media platform with governance and revenue distribution
 */
contract CommunityOwnedMediaDAO {

    address public admin;
    uint256 public proposalCount;
    uint256 public memberCount;

    constructor() {
        admin = msg.sender;
    }

    // -------------------- STRUCTS --------------------

    struct Member {
        bool active;
        uint256 votingPower;
        uint256 rewardBalance;
    }

    struct Proposal {
        string description;
        uint256 yesVotes;
        uint256 noVotes;
        uint256 deadline;
        bool executed;
    }

    mapping(address => Member) public members;
    mapping(uint256 => Proposal) public proposals;

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

    event MemberJoined(address indexed member, uint256 votingPower);
    event ProposalCreated(uint256 indexed proposalId, string description);
    event Voted(uint256 indexed proposalId, address indexed voter, bool support, uint256 weight);
    event ProposalExecuted(uint256 indexed proposalId);
    event RevenueDistributed(uint256 amount);
    event RewardWithdrawn(address indexed member, uint256 amount);

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

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

    // -------------------- MEMBERSHIP --------------------

    function joinDAO(uint256 _votingPower) external {
        require(!members[msg.sender].active, "Already member");
        require(_votingPower > 0, "Invalid voting power");

        members[msg.sender] = Member({
            active: true,
            votingPower: _votingPower,
            rewardBalance: 0
        });

        memberCount += 1;
        emit MemberJoined(msg.sender, _votingPower);
    }

    // -------------------- GOVERNANCE --------------------

    function createProposal(string calldata _description, uint256 _votingDuration)
        external
        onlyMember
    {
        require(_votingDuration > 0, "Invalid duration");

        proposalCount += 1;
        proposals[proposalCount] = Proposal({
            description: _description,
            yesVotes: 0,
            noVotes: 0,
            deadline: block.timestamp + _votingDuration,
            executed: false
        });

        emit ProposalCreated(proposalCount, _description);
    }

    function vote(uint256 _proposalId, bool _support) external onlyMember {
        Proposal storage p = proposals[_proposalId];
        require(block.timestamp <p>= p.deadline, "Voting ongoing");
        require(!p.executed, "Already executed");

        require(p.yesVotes &gt; p.noVotes, "Proposal rejected");
        p.executed = true;

        emit ProposalExecuted(_proposalId);
    }

    // -------------------- TREASURY &amp; REVENUE --------------------

    receive() external payable {}

    function distributeRevenue(address[] calldata _contributors, uint256[] calldata _amounts)
        external
        payable
    {
        require(_contributors.length == _amounts.length, "Length mismatch");

        uint256 total;
        for (uint256 i = 0; i &lt; _amounts.length; i++) {
            total += _amounts[i];
        }
        require(total == msg.value, &quot;Invalid distribution&quot;);

        for (uint256 i = 0; i  0, "No rewards");

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

        emit RewardWithdrawn(msg.sender, amount);
    }
}