Recall Management Contract
What it does:
Registers and manages product recalls, tracking affected batches, notifying stakeholders, and ensuring compliance with safety regulations.
Why it matters:
Reduces risk to consumers, ensures timely recall actions, prevents fraud, and provides auditable evidence of recall management.
How it works:
-
Manufacturers register recalled batches or products on-chain
-
Batch IDs and affected product details are logged immutably
-
Notifications are sent to distributors, retailers, and consumers (off-chain integration possible)
-
Ownership and custody of recalled items are tracked for proper handling
-
Smart contracts maintain historical recall records for compliance and auditing
-
Integrates with Supply Chain Traceability, Inventory Management, and marketplaces
-
Public dashboards display recalled products and their status
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title RecallManagement
* @author Nam
* @notice Manages product recalls on-chain with batch tracking and event logging
*/
contract RecallManagement is Ownable {
struct Batch {
string metadataURI;
bool exists;
bool recalled;
}
struct RecallEvent {
uint256 timestamp;
string reason;
address reporter;
}
mapping(uint256 => Batch) public batches; // batchId => Batch
mapping(uint256 => RecallEvent[]) public recallEvents; // batchId => events
uint256 public batchCount;
mapping(address => bool) public authorizedReporters;
// -------------------- EVENTS --------------------
event BatchRegistered(uint256 indexed batchId, string metadataURI);
event RecallEventLogged(uint256 indexed batchId, string reason, address reporter);
event BatchRecalled(uint256 indexed batchId);
event ReporterApproved(address reporter);
// -------------------- REPORTER MANAGEMENT --------------------
function approveReporter(address _reporter) external onlyOwner {
authorizedReporters[_reporter] = true;
emit ReporterApproved(_reporter);
}
function revokeReporter(address _reporter) external onlyOwner {
authorizedReporters[_reporter] = false;
}
modifier onlyReporter() {
require(authorizedReporters[msg.sender], "Not an authorized reporter");
_;
}
// -------------------- BATCH MANAGEMENT --------------------
function registerBatch(string calldata _metadataURI) external onlyReporter {
batchCount += 1;
batches[batchCount] = Batch({
metadataURI: _metadataURI,
exists: true,
recalled: false
});
emit BatchRegistered(batchCount, _metadataURI);
}
// -------------------- RECALL MANAGEMENT --------------------
function logRecallEvent(uint256 _batchId, string calldata _reason) external onlyReporter {
require(batches[_batchId].exists, "Batch does not exist");
recallEvents[_batchId].push(RecallEvent({
timestamp: block.timestamp,
reason: _reason,
reporter: msg.sender
}));
batches[_batchId].recalled = true;
emit RecallEventLogged(_batchId, _reason, msg.sender);
emit BatchRecalled(_batchId);
}
// -------------------- VIEW FUNCTIONS --------------------
function getRecallEvents(uint256 _batchId) external view returns (RecallEvent[] memory) {
return recallEvents[_batchId];
}
function isBatchRecalled(uint256 _batchId) external view returns (bool) {
return batches[_batchId].recalled;
}
}