Carbon Credit Trading Contract

What it does:
Tokenizes carbon credits as on-chain assets, enabling transparent issuance, transfer, trading, and retirement of verified emissions reductions.

Why it matters:
Prevents double-counting, increases trust in carbon markets, reduces reliance on opaque intermediaries, and makes climate action auditable and global.

How it works:

  • Verified projects issue carbon credits as on-chain tokens

  • Each token represents a fixed amount of CO₂ offset (e.g. 1 ton)

  • Credits can be transferred or traded on secondary markets

  • Buyers retire credits on-chain to offset emissions

  • Retired credits are permanently removed from circulation

  • All issuance, transfers, and retirements are publicly auditable

  • Integrates with registries, oracles, and sustainability reporting tools

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

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

/**
 * @title CarbonCreditToken
 * @author Nam
 * @notice Tokenized carbon credits with on-chain retirement
 */
contract CarbonCreditToken is ERC20, Ownable {

    uint256 public retiredSupply;

    mapping(address => uint256) public retiredBalance;
    mapping(bytes32 => bool) public retiredReferences; 
    // e.g. company report IDs to prevent double claims

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

    event CreditsIssued(address indexed project, uint256 amount);
    event CreditsRetired(address indexed account, uint256 amount, bytes32 referenceId);

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

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

    // -------------------- ISSUANCE --------------------

    function issueCredits(address _to, uint256 _amount) external onlyOwner {
        require(_amount > 0, "Invalid amount");
        _mint(_to, _amount);

        emit CreditsIssued(_to, _amount);
    }

    // -------------------- RETIREMENT --------------------

    function retireCredits(uint256 _amount, bytes32 _referenceId) external {
        require(_amount > 0, "Invalid amount");
        require(balanceOf(msg.sender) >= _amount, "Insufficient balance");
        require(!retiredReferences[_referenceId], "Reference already used");

        _burn(msg.sender, _amount);

        retiredSupply += _amount;
        retiredBalance[msg.sender] += _amount;
        retiredReferences[_referenceId] = true;

        emit CreditsRetired(msg.sender, _amount, _referenceId);
    }

    // -------------------- VIEW --------------------

    function totalActiveSupply() external view returns (uint256) {
        return totalSupply();
    }
}