Recycling Reward Smart Contract

What it does:
Rewards individuals or organizations with tokens for verified recycling actions, turning sustainable behavior into on-chain, measurable incentives.

Why it matters:
Encourages real-world recycling through economic rewards, creates transparent environmental impact records, and aligns individual actions with sustainability goals.

How it works:

  • Recycling centers or IoT devices verify recycling actions off-chain

  • Verified data is submitted on-chain via trusted oracles

  • Smart contract mints or distributes reward tokens per verified action

  • Rewards are based on material type, weight, or environmental impact

  • Users accumulate on-chain rewards tied to their wallet

  • Fraud is reduced through unique action IDs and oracle validation

  • Recycling data is auditable for ESG reporting and analytics

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

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

/**
 * @title RecyclingRewardToken
 * @author Nam
 * @notice Rewards verified recycling actions with on-chain tokens
 */
contract RecyclingRewardToken is ERC20, Ownable {

    struct RecyclingAction {
        address recycler;
        uint256 weight; // in grams or kg (agreed unit)
        uint256 reward;
        bool rewarded;
    }

    mapping(bytes32 => RecyclingAction) public actions;
    mapping(address => bool) public approvedOracles;

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

    event OracleApproved(address indexed oracle);
    event RecyclingRecorded(bytes32 indexed actionId, address indexed recycler, uint256 weight);
    event RewardIssued(address indexed recycler, uint256 amount);

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

    constructor(
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol) {}

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

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

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

    // -------------------- RECYCLING LOGIC --------------------

    function recordRecycling(
        bytes32 _actionId,
        address _recycler,
        uint256 _weight,
        uint256 _rewardAmount
    ) external {
        require(approvedOracles[msg.sender], "Not authorized oracle");
        require(actions[_actionId].recycler == address(0), "Action exists");
        require(_weight > 0 && _rewardAmount > 0, "Invalid data");

        actions[_actionId] = RecyclingAction({
            recycler: _recycler,
            weight: _weight,
            reward: _rewardAmount,
            rewarded: false
        });

        emit RecyclingRecorded(_actionId, _recycler, _weight);
    }

    function issueReward(bytes32 _actionId) external {
        RecyclingAction storage a = actions[_actionId];
        require(approvedOracles[msg.sender], "Not authorized oracle");
        require(!a.rewarded, "Already rewarded");

        a.rewarded = true;
        _mint(a.recycler, a.reward);

        emit RewardIssued(a.recycler, a.reward);
    }
}