Ocean Cleanup Reward DAO

What it does:
Rewards individuals, NGOs, and organizations for verified ocean and coastal cleanup activities using a decentralized, impact-based incentive system.

Why it matters:
Addresses marine pollution at scale by aligning financial incentives with measurable environmental impact while ensuring transparency and trust in cleanup efforts.

How it works:

  • Cleanup participants submit cleanup reports with evidence hashes (photos, videos, sensor data)

  • Independent verifiers or DAO members validate reported cleanup activities

  • Verified cleanup data (weight, area, type of waste) is recorded on-chain

  • Rewards are calculated based on verified impact metrics

  • Tokens or funds are distributed automatically from the DAO treasury

  • DAO governance adjusts reward rates and verification rules

  • Public dashboards display cleanup impact and funding usage

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

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

/**
 * @title OceanCleanupRewardDAO
 * @author Nam
 * @notice DAO-based reward system for verified ocean cleanup activities
 */
contract OceanCleanupRewardDAO is Ownable {

    IERC20 public rewardToken;

    struct CleanupReport {
        address cleaner;
        string evidenceURI; // IPFS / Arweave
        uint256 wasteKg;
        bool verified;
        bool rewarded;
    }

    uint256 public reportCount;
    uint256 public rewardPerKg; // token reward per kg of waste

    mapping(uint256 => CleanupReport) public reports;
    mapping(address => bool) public verifiers;

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

    event ReportSubmitted(uint256 indexed reportId, address indexed cleaner, uint256 wasteKg);
    event ReportVerified(uint256 indexed reportId);
    event RewardPaid(address indexed cleaner, uint256 amount);

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

    constructor(address _rewardToken, uint256 _rewardPerKg) {
        rewardToken = IERC20(_rewardToken);
        rewardPerKg = _rewardPerKg;
    }

    // -------------------- VERIFIER MANAGEMENT --------------------

    function approveVerifier(address _verifier) external onlyOwner {
        verifiers[_verifier] = true;
    }

    // -------------------- REPORT SUBMISSION --------------------

    function submitCleanupReport(
        string calldata _evidenceURI,
        uint256 _wasteKg
    ) external {
        require(_wasteKg > 0, "Invalid waste amount");

        reportCount += 1;
        reports[reportCount] = CleanupReport({
            cleaner: msg.sender,
            evidenceURI: _evidenceURI,
            wasteKg: _wasteKg,
            verified: false,
            rewarded: false
        });

        emit ReportSubmitted(reportCount, msg.sender, _wasteKg);
    }

    // -------------------- VERIFICATION --------------------

    function verifyReport(uint256 _reportId) external {
        require(verifiers[msg.sender], "Not verifier");

        CleanupReport storage r = reports[_reportId];
        require(!r.verified, "Already verified");

        r.verified = true;
        emit ReportVerified(_reportId);
    }

    // -------------------- REWARD CLAIM --------------------

    function claimReward(uint256 _reportId) external {
        CleanupReport storage r = reports[_reportId];
        require(r.verified, "Not verified");
        require(!r.rewarded, "Already rewarded");
        require(msg.sender == r.cleaner, "Not cleaner");

        uint256 reward = r.wasteKg * rewardPerKg;
        require(rewardToken.balanceOf(address(this)) >= reward, "Insufficient funds");

        r.rewarded = true;
        rewardToken.transfer(msg.sender, reward);

        emit RewardPaid(msg.sender, reward);
    }
}