Tree Planting Verification Contract

What it does:
Verifies, records, and rewards tree planting activities using on-chain proof, ensuring that reforestation claims are real, measurable, and auditable.

Why it matters:
Prevents fake tree-planting claims, increases trust in reforestation initiatives, supports carbon sequestration accounting, and enables transparent environmental impact reporting.

How it works:

  • Tree planters or organizations register planting projects on-chain

  • Each tree planting event is documented with metadata (location, species, date)

  • Approved oracles verify planting via satellite data, IoT, or field audits

  • Verified trees are recorded as immutable on-chain records

  • Survival or growth milestones can be tracked over time

  • Verified trees generate impact credits or rewards

  • All planting and verification data is 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 TreePlantingVerification
 * @author Nam
 * @notice Verifies tree planting and distributes rewards for reforestation
 */
contract TreePlantingVerification is Ownable {

    IERC20 public rewardToken;

    struct Tree {
        address planter;
        string metadataURI; // IPFS: location, species, photos
        uint256 plantedAt;
        bool verified;
        uint256 rewardClaimed;
    }

    uint256 public treeCount;
    mapping(uint256 => Tree) public trees;
    mapping(address => bool) public approvedOracles;

    uint256 public baseReward = 1e18; // reward per verified tree

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

    event TreeRegistered(uint256 indexed treeId, address indexed planter);
    event TreeVerified(uint256 indexed treeId, address indexed oracle);
    event RewardClaimed(uint256 indexed treeId, address indexed planter, 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;
    }

    // -------------------- TREE REGISTRATION --------------------

    function registerTree(string calldata _metadataURI) external {
        treeCount += 1;
        trees[treeCount] = Tree({
            planter: msg.sender,
            metadataURI: _metadataURI,
            plantedAt: block.timestamp,
            verified: false,
            rewardClaimed: 0
        });

        emit TreeRegistered(treeCount, msg.sender);
    }

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

    function verifyTree(uint256 _treeId) external {
        require(approvedOracles[msg.sender], "Not authorized oracle");
        Tree storage t = trees[_treeId];
        require(!t.verified, "Already verified");

        t.verified = true;
        emit TreeVerified(_treeId, msg.sender);
    }

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

    function claimReward(uint256 _treeId) external {
        Tree storage t = trees[_treeId];
        require(t.planter == msg.sender, "Not planter");
        require(t.verified, "Tree not verified");
        require(t.rewardClaimed == 0, "Reward already claimed");

        t.rewardClaimed = baseReward;
        rewardToken.transfer(msg.sender, baseReward);

        emit RewardClaimed(_treeId, msg.sender, baseReward);
    }
}