Product Authenticity Verification

What it does:
Verifies and records the authenticity and provenance of products on-chain, ensuring buyers and stakeholders can trust origin, ownership, and history.

Why it matters:
Prevents counterfeiting, improves transparency in supply chains, and builds consumer confidence in product authenticity.

How it works:

  • Manufacturers or suppliers register products with metadata, serial numbers, and provenance details

  • Each product is assigned a unique on-chain identifier or NFT

  • Ownership transfers, supply chain events, and certifications are logged immutably

  • Buyers and auditors can verify authenticity and trace the product journey

  • Smart contracts can trigger alerts for counterfeit detection

  • Integrates with marketplaces, warranty systems, or logistics tracking

  • Public dashboards display provenance history and authenticity status

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

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

/**
 * @title ProductAuthenticityVerification
 * @author Nam
 * @notice Tracks product authenticity and provenance on-chain using NFTs
 */
contract ProductAuthenticityVerification is ERC721, Ownable {

    struct Product {
        string metadataURI; // e.g., IPFS or product info
        uint256 creationTimestamp;
        address currentOwner;
    }

    mapping(uint256 => Product) public products;
    uint256 public productCount;

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

    event ProductRegistered(uint256 indexed productId, address indexed manufacturer);
    event OwnershipTransferred(uint256 indexed productId, address indexed from, address indexed to);

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

    constructor() ERC721("ProductAuthenticityNFT", "PANFT") {}

    // -------------------- PRODUCT MANAGEMENT --------------------

    function registerProduct(address _manufacturer, string calldata _metadataURI) external onlyOwner {
        require(_manufacturer != address(0), "Invalid manufacturer");

        productCount += 1;
        uint256 productId = productCount;

        _safeMint(_manufacturer, productId);

        products[productId] = Product({
            metadataURI: _metadataURI,
            creationTimestamp: block.timestamp,
            currentOwner: _manufacturer
        });

        emit ProductRegistered(productId, _manufacturer);
    }

    // -------------------- OWNERSHIP TRACKING --------------------

    function transferProduct(uint256 _productId, address _to) external {
        require(ownerOf(_productId) == msg.sender, "Not the product owner");
        require(_to != address(0), "Invalid recipient");

        _transfer(msg.sender, _to, _productId);
        products[_productId].currentOwner = _to;

        emit OwnershipTransferred(_productId, msg.sender, _to);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    function getProduct(uint256 _productId) external view returns (Product memory) {
        return products[_productId];
    }

    function verifyOwnership(uint256 _productId, address _user) external view returns (bool) {
        return ownerOf(_productId) == _user;
    }
}