Environmental Impact DAO

What it does:
A decentralized autonomous organization that funds, tracks, and governs environmental impact projects such as reforestation, clean water, biodiversity protection, and climate research.

Why it matters:
Replaces opaque NGO and government funding with transparent, community-driven decision-making, ensures accountability of impact claims, and aligns incentives around measurable environmental outcomes.

How it works:

  • Members join the DAO by holding governance tokens

  • Proposals are submitted for environmental projects and initiatives

  • Each proposal includes funding requests and impact metrics (e.g. CO₂ offset, trees planted)

  • Token holders vote on which projects receive funding

  • Approved proposals receive funds via smart contract escrow

  • Project teams submit impact reports verified by oracles or auditors

  • DAO treasury and impact data remain fully transparent and auditable

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title EnvironmentalImpactDAO
 * @author Nam
 * @notice DAO for funding and governing environmental impact projects
 */
contract EnvironmentalImpactDAO is Ownable {

    IERC20 public governanceToken;

    uint256 public proposalCount;
    uint256 public votingPeriod = 5 days;
    uint256 public quorumPercentage = 10; // % of total supply

    struct Proposal {
        address proposer;
        address payable recipient;
        uint256 amount;
        string description;
        string impactMetrics; // expected environmental outcomes
        uint256 votesFor;
        uint256 votesAgainst;
        uint256 endTime;
        bool executed;
    }

    mapping(uint256 => Proposal) public proposals;
    mapping(uint256 => mapping(address => bool)) public hasVoted;

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

    event ProposalCreated(uint256 indexed proposalId, address proposer, uint256 amount);
    event Voted(uint256 indexed proposalId, address voter, bool support, uint256 weight);
    event ProposalExecuted(uint256 indexed proposalId);

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

    constructor(address _governanceToken) {
        governanceToken = IERC20(_governanceToken);
    }

    // -------------------- PROPOSALS --------------------

    function createProposal(
        address payable _recipient,
        uint256 _amount,
        string calldata _description,
        string calldata _impactMetrics
    ) external {
        require(governanceToken.balanceOf(msg.sender) > 0, "Not a DAO member");
        require(_amount > 0, "Invalid amount");

        proposalCount += 1;
        proposals[proposalCount] = Proposal({
            proposer: msg.sender,
            recipient: _recipient,
            amount: _amount,
            description: _description,
            impactMetrics: _impactMetrics,
            votesFor: 0,
            votesAgainst: 0,
            endTime: block.timestamp + votingPeriod,
            executed: false
        });

        emit ProposalCreated(proposalCount, msg.sender, _amount);
    }

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

    function vote(uint256 _proposalId, bool _support) external {
        Proposal storage p = proposals[_proposalId];
        require(block.timestamp <p> 0, "No voting power");

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

        if (_support) {
            p.votesFor += weight;
        } else {
            p.votesAgainst += weight;
        }

        emit Voted(_proposalId, msg.sender, _support, weight);
    }

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

    function executeProposal(uint256 _proposalId) external {
        Proposal storage p = proposals[_proposalId];
        require(block.timestamp &gt;= p.endTime, "Voting not ended");
        require(!p.executed, "Already executed");

        uint256 totalVotes = p.votesFor + p.votesAgainst;
        uint256 quorum = (governanceToken.totalSupply() * quorumPercentage) / 100;

        require(totalVotes &gt;= quorum, "Quorum not reached");
        require(p.votesFor &gt; p.votesAgainst, "Proposal rejected");
        require(address(this).balance &gt;= p.amount, "Insufficient treasury");

        p.executed = true;
        p.recipient.transfer(p.amount);

        emit ProposalExecuted(_proposalId);
    }

    // -------------------- TREASURY --------------------

    receive() external payable {}
}