Climate Research Funding DAO

What it does:
Funds climate-related scientific research through a decentralized, transparent DAO that allocates capital to high-impact studies and innovations.

Why it matters:
Accelerates climate science by removing bureaucratic bottlenecks, improves trust in research funding, and aligns incentives around measurable scientific and environmental outcomes.

How it works:

  • Researchers and institutions submit funding proposals on-chain

  • Proposals include research goals, methodology, budget, and impact metrics

  • DAO members hold governance tokens and review proposals

  • Token holders vote to approve or reject funding requests

  • Approved funds are held in escrow and released by milestones

  • Research outputs and data are published via on-chain references

  • All funding decisions and results are transparent and auditable

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

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

/**
 * @title ClimateResearchFundingDAO
 * @author Nam
 * @notice DAO for funding climate research with milestone-based payouts
 */
contract ClimateResearchFundingDAO is Ownable {

    IERC20 public governanceToken;

    uint256 public proposalCount;
    uint256 public votingPeriod = 7 days;
    uint256 public quorumPercentage = 15; // % of total supply

    struct Proposal {
        address proposer;
        address payable recipient;
        uint256 totalAmount;
        uint256 releasedAmount;
        string description;
        string impactMetrics;
        uint256 endTime;
        uint256 votesFor;
        uint256 votesAgainst;
        bool approved;
    }

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

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

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

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

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

    // -------------------- PROPOSAL SUBMISSION --------------------

    function submitProposal(
        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,
            totalAmount: _amount,
            releasedAmount: 0,
            description: _description,
            impactMetrics: _impactMetrics,
            endTime: block.timestamp + votingPeriod,
            votesFor: 0,
            votesAgainst: 0,
            approved: false
        });

        emit ProposalSubmitted(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);
    }

    // -------------------- APPROVAL &amp; ESCROW --------------------

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

        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");

        p.approved = true;
    }

    // -------------------- MILESTONE PAYOUT --------------------

    function releaseFunds(uint256 _proposalId, uint256 _amount) external onlyOwner {
        Proposal storage p = proposals[_proposalId];
        require(p.approved, "Not approved");
        require(p.releasedAmount + _amount = _amount, "Insufficient DAO funds");

        p.releasedAmount += _amount;
        p.recipient.transfer(_amount);

        emit FundsReleased(_proposalId, _amount);
    }

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

    receive() external payable {}
}