Retail Loyalty Smart Contract

What it does:
Manages loyalty points, rewards, and tiered benefits for retail customers, automatically issuing points for purchases and redeeming rewards on-chain.

Why it matters:
Enhances customer engagement, prevents fraud, provides transparent reward tracking, and reduces manual loyalty program management.

How it works:

  • Retailers register customers on-chain

  • Purchases are tracked and loyalty points are credited automatically

  • Customers can redeem points for discounts, tokens, or special offers

  • Tiered programs can reward frequent or high-value customers

  • Points and rewards are auditable and transferable (optional)

  • Integrates with POS systems, marketplaces, and token-based reward ecosystems

  • Dashboards display customer points, reward history, and redemption options

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

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

/**
 * @title RetailLoyalty
 * @author Nam
 * @notice Tracks customer loyalty points and manages rewards on-chain
 */
contract RetailLoyalty is Ownable {

    struct Customer {
        uint256 points;
        bool registered;
    }

    mapping(address => Customer) public customers;

    mapping(address => bool) public authorizedRetailers;

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

    event CustomerRegistered(address customer);
    event PointsAccrued(address customer, uint256 points);
    event PointsRedeemed(address customer, uint256 points, string reward);
    event RetailerApproved(address retailer);

    // -------------------- RETAILER MANAGEMENT --------------------

    function approveRetailer(address _retailer) external onlyOwner {
        authorizedRetailers[_retailer] = true;
        emit RetailerApproved(_retailer);
    }

    function revokeRetailer(address _retailer) external onlyOwner {
        authorizedRetailers[_retailer] = false;
    }

    modifier onlyRetailer() {
        require(authorizedRetailers[msg.sender], "Not an authorized retailer");
        _;
    }

    // -------------------- CUSTOMER MANAGEMENT --------------------

    function registerCustomer(address _customer) external onlyRetailer {
        require(!customers[_customer].registered, "Already registered");

        customers[_customer] = Customer({
            points: 0,
            registered: true
        });

        emit CustomerRegistered(_customer);
    }

    // -------------------- POINTS MANAGEMENT --------------------

    function accruePoints(address _customer, uint256 _points) external onlyRetailer {
        require(customers[_customer].registered, "Customer not registered");

        customers[_customer].points += _points;
        emit PointsAccrued(_customer, _points);
    }

    function redeemPoints(address _customer, uint256 _points, string calldata _reward) external onlyRetailer {
        Customer storage c = customers[_customer];
        require(c.registered, "Customer not registered");
        require(c.points >= _points, "Insufficient points");

        c.points -= _points;
        emit PointsRedeemed(_customer, _points, _reward);
    }

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

    function getCustomerPoints(address _customer) external view returns (uint256) {
        return customers[_customer].points;
    }
}