Environmental Violation Reporting

What it does:
Enables citizens, NGOs, and inspectors to report environmental violations (illegal dumping, pollution, deforestation, emissions fraud) in a tamper-proof, transparent, and incentive-aligned system.

Why it matters:
Reduces corruption, protects whistleblowers, creates immutable evidence trails, and increases accountability for environmental harm.

How it works:

  • Reporters submit violation evidence hashes (photos, videos, sensor data) on-chain

  • Reports are anonymized or pseudonymous to protect whistleblowers

  • Verified reviewers or a DAO assess report credibility

  • Verified violations trigger penalties, fines, or remediation actions

  • Optional bounties or rewards are paid to reporters

  • Case status updates are tracked immutably

  • Public dashboards show aggregated violation data

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

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

/**
 * @title EnvironmentalViolationReporting
 * @author Nam
 * @notice On-chain reporting and verification of environmental violations
 */
contract EnvironmentalViolationReporting is Ownable {

    IERC20 public rewardToken;

    enum Status { Submitted, UnderReview, Verified, Rejected }

    struct Report {
        address reporter;
        string evidenceHash; // IPFS / Arweave hash
        string location;     // optional geo reference
        Status status;
        uint256 reward;
    }

    uint256 public reportCount;
    mapping(uint256 => Report) public reports;
    mapping(address => bool) public reviewers;

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

    event ReportSubmitted(uint256 indexed reportId, string evidenceHash);
    event ReviewerApproved(address reviewer);
    event ReportReviewed(uint256 indexed reportId, Status status);
    event RewardPaid(uint256 indexed reportId, address reporter, uint256 amount);

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

    constructor(address _rewardToken) {
        rewardToken = IERC20(_rewardToken);
    }

    // -------------------- REVIEWER MANAGEMENT --------------------

    function approveReviewer(address _reviewer) external onlyOwner {
        reviewers[_reviewer] = true;
        emit ReviewerApproved(_reviewer);
    }

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

    function submitReport(
        string calldata _evidenceHash,
        string calldata _location
    ) external {
        require(bytes(_evidenceHash).length > 0, "Evidence required");

        reportCount += 1;
        reports[reportCount] = Report({
            reporter: msg.sender,
            evidenceHash: _evidenceHash,
            location: _location,
            status: Status.Submitted,
            reward: 0
        });

        emit ReportSubmitted(reportCount, _evidenceHash);
    }

    // -------------------- REPORT REVIEW --------------------

    function reviewReport(
        uint256 _reportId,
        bool _verified,
        uint256 _reward
    ) external {
        require(reviewers[msg.sender], "Not authorized reviewer");
        Report storage r = reports[_reportId];
        require(r.status == Status.Submitted || r.status == Status.UnderReview, "Invalid status");

        if (_verified) {
            r.status = Status.Verified;
            r.reward = _reward;
        } else {
            r.status = Status.Rejected;
        }

        emit ReportReviewed(_reportId, r.status);
    }

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

    function claimReward(uint256 _reportId) external {
        Report storage r = reports[_reportId];
        require(r.status == Status.Verified, "Not verified");
        require(msg.sender == r.reporter, "Not reporter");
        require(r.reward > 0, "No reward");

        uint256 amount = r.reward;
        r.reward = 0;

        rewardToken.transfer(msg.sender, amount);
        emit RewardPaid(_reportId, msg.sender, amount);
    }
}