Plastic Reduction Reward System

What it does:
Rewards individuals, businesses, and communities for verified actions that reduce plastic usage and plastic waste.

Why it matters:
Plastic pollution is one of the largest environmental threats; transparent, impact-based incentives accelerate behavior change and make reduction efforts measurable and accountable.

How it works:

  • Participants register reduction accounts on-chain

  • Approved oracles verify plastic reduction activities (reuse, alternatives, collection)

  • Each verified activity is converted into plastic-reduction units (kg / items)

  • Reduction units accumulate as on-chain impact scores

  • Smart contracts calculate rewards based on verified impact

  • Rewards are distributed automatically in tokens or credits

  • All reduction data is auditable and usable for ESG reporting

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

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

/**
 * @title PlasticReductionReward
 * @author Nam
 * @notice Rewards verified plastic waste reduction activities
 */
contract PlasticReductionReward is Ownable {

    IERC20 public rewardToken;

    struct Participant {
        bool registered;
        uint256 reducedAmount; // total plastic reduced (kg or units)
        uint256 rewardsClaimed;
    }

    mapping(address => Participant) public participants;
    mapping(address => bool) public approvedOracles;

    uint256 public rewardRate = 1e18; // tokens per unit of plastic reduced

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

    event ParticipantRegistered(address indexed participant);
    event PlasticReductionVerified(address indexed participant, uint256 amount);
    event RewardClaimed(address indexed participant, uint256 amount);

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

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

    // -------------------- ORACLE MANAGEMENT --------------------

    function approveOracle(address _oracle) external onlyOwner {
        approvedOracles[_oracle] = true;
    }

    function revokeOracle(address _oracle) external onlyOwner {
        approvedOracles[_oracle] = false;
    }

    // -------------------- PARTICIPANT MANAGEMENT --------------------

    function registerParticipant() external {
        require(!participants[msg.sender].registered, "Already registered");

        participants[msg.sender] = Participant({
            registered: true,
            reducedAmount: 0,
            rewardsClaimed: 0
        });

        emit ParticipantRegistered(msg.sender);
    }

    // -------------------- REDUCTION VERIFICATION --------------------

    function verifyReduction(address _participant, uint256 _amount) external {
        require(approvedOracles[msg.sender], "Not authorized oracle");
        require(participants[_participant].registered, "Not registered");
        require(_amount > 0, "Invalid reduction amount");

        participants[_participant].reducedAmount += _amount;
        emit PlasticReductionVerified(_participant, _amount);
    }

    // -------------------- REWARD CLAIMING --------------------

    function claimReward(uint256 _amount) external {
        Participant storage p = participants[msg.sender];
        require(p.registered, "Not registered");

        uint256 maxReward = p.reducedAmount * rewardRate;
        uint256 available = maxReward - p.rewardsClaimed;
        require(_amount <= available, "Exceeds available reward");

        p.rewardsClaimed += _amount;
        rewardToken.transfer(msg.sender, _amount);

        emit RewardClaimed(msg.sender, _amount);
    }
}