Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Blockchain-Based Supply Chain Provenance System

A developer tutorial for building an end-to-end traceability solution that records product origin, movement, and authenticity on-chain using IoT sensors and standardized data.
Chainscore © 2026
introduction
TUTORIAL

Setting Up a Blockchain-Based Supply Chain Provenance System

A practical guide to implementing a provenance system using smart contracts, from defining data models to tracking on-chain events.

A blockchain-based provenance system creates an immutable, transparent ledger for a product's journey. At its core, it records key events—like manufacturing, quality checks, and transfers of custody—as transactions on a blockchain. This provides a single source of truth that is verifiable by all participants, from suppliers to end consumers. Unlike traditional databases, the decentralized nature of blockchain prevents any single entity from altering historical records, establishing trust in the data. Common platforms for building these systems include Ethereum, Polygon, and Solana, chosen for their smart contract capabilities and developer ecosystems.

The first technical step is designing the smart contract data model. You must define the structure for your digital asset, often an ERC-721 or ERC-1155 non-fungible token (NFT) representing a unique product batch. The smart contract state should store critical attributes like productId, manufacturer, creationTimestamp, and a dynamic array of Event structs. Each Event could contain fields for eventType (e.g., "Shipped"), location, timestamp, and actor (the Ethereum address of the entity performing the action). This on-chain history forms the auditable trail.

Here is a simplified Solidity example for a provenance contract skeleton:

solidity
event ProductEvent(uint256 indexed productId, string eventType, string details);
mapping(uint256 => Product) public products;
function recordEvent(uint256 _productId, string memory _eventType, string memory _details) external {
    // Access control logic here
    emit ProductEvent(_productId, _eventType, _details);
}

The ProductEvent emit is crucial; it creates a permanent, queryable log on the blockchain. Off-chain applications listen for these events to update user interfaces and databases. Access control via modifiers like onlyOwner or role-based systems (using OpenZeppelin's AccessControl) is essential to ensure only authorized parties can record events.

Integrating real-world data requires oracles and off-chain computation. Physical sensors (IoT devices) or enterprise ERP systems generate data that must be relayed to the blockchain. Services like Chainlink Oracles provide a secure bridge for this. For complex or private data, consider a hybrid approach: store cryptographic hashes (e.g., SHA-256) of documents or sensor readings on-chain, while keeping the full data in decentralized storage like IPFS or Arweave. Consumers can then verify the off-chain data matches the on-chain hash, ensuring integrity without bloating the chain.

Finally, you must build the user-facing application. A frontend (using a framework like React) interacts with the smart contract via a library such as ethers.js or viem. It calls the recordEvent function for authorized users and queries past events using the contract's public mapping or by filtering the ProductEvent logs. For scalability, consider indexing the events with a service like The Graph to enable fast, complex queries about product history. The end result is a dashboard where a user can scan a QR code on a physical product and view its complete, tamper-evident lifecycle story.

prerequisites
FOUNDATION

Prerequisites and Tech Stack

A blockchain-based supply chain provenance system requires a specific technical foundation. This guide outlines the core software, tools, and knowledge needed before development begins.

Building a supply chain provenance system requires a clear understanding of the underlying blockchain technology. You should be comfortable with core Web3 concepts like public/private key cryptography, decentralized consensus, and immutable ledgers. Familiarity with smart contracts is essential, as they encode the business logic for tracking assets, recording ownership transfers, and verifying authenticity on-chain. For most enterprise applications, you'll choose between a permissioned blockchain (like Hyperledger Fabric) for controlled access or a public Layer 2 solution (like Polygon or Arbitrum) for cost efficiency and interoperability.

Your development environment must be properly configured. Start by installing Node.js (v18 LTS or later) and a package manager like npm or yarn. You will need a code editor such as Visual Studio Code with Solidity extensions. The primary tool for smart contract development is the Hardhat or Foundry framework, which provides testing, compilation, and deployment pipelines. You'll also need the MetaMask browser extension to interact with your application and a faucet to obtain testnet ETH (e.g., from Sepolia Faucet) for deploying contracts.

The core of your stack is the smart contract language. Solidity is the industry standard for Ethereum Virtual Machine (EVM) chains. Your contracts will define critical data structures: a unique Product struct with fields like id, batchNumber, manufacturer, and timestamp, and a Transfer struct to log each custody change. You will use mappings to link products to their history. For off-chain data and file storage, integrate the InterPlanetary File System (IPFS) via a service like Pinata to store certificates of authenticity, images, or detailed documentation, storing only the content hash (CID) on-chain.

To connect your front-end application to the blockchain, you will use a library like ethers.js or viem. You'll need to set up a provider to connect to a blockchain node; services like Alchemy or Infura provide reliable RPC endpoints. For indexing and querying complex event data from your contracts efficiently, consider using The Graph protocol to create a subgraph. This allows your dApp to query product histories with GraphQL instead of making slow direct chain calls.

Finally, consider the ancillary tools for a robust system. Use OpenZeppelin Contracts for audited, secure base implementations like Ownable for access control. Implement Chainlink Oracles if you need to bring real-world data (like temperature logs from IoT sensors) on-chain. For testing, write comprehensive unit and integration tests in Hardhat using Chai and Mocha. Plan your deployment strategy, including contract verification on block explorers like Etherscan and considering upgrade patterns using proxies if business logic may evolve.

system-architecture
SUPPLY CHAIN PROVENANCE

System Architecture Overview

A blockchain-based provenance system provides an immutable, transparent ledger for tracking goods from origin to consumer. This guide outlines the core architectural components required to build a functional and secure system.

A supply chain provenance system built on blockchain is a decentralized application (dApp) that records the lifecycle of a product as a series of immutable events. The architecture typically follows a three-tier model: a smart contract layer on-chain, a backend service layer off-chain, and a client-facing application layer. The smart contracts define the data model—such as Product, Batch, and Transfer—and enforce the business logic for state transitions, ensuring that only authorized parties can update a product's status. This creates a single source of truth that is verifiable by all participants.

The off-chain backend is crucial for handling data and events that are impractical to store directly on-chain due to cost or size. This layer often includes an indexing service (like The Graph) to query event logs efficiently, a file storage solution (like IPFS or Arweave) for certificates and high-resolution images, and an oracle service to bring real-world data (e.g., IoT sensor readings, customs data) onto the blockchain. These components bridge the gap between the deterministic blockchain environment and the messy, data-rich physical world of supply chains.

For a concrete example, consider tracking organic coffee. A Product NFT is minted representing a harvest batch. Each step—Harvested by Farmer A, Shipped by Logistics Co. B, Roasted by Processor C—is recorded as a transaction, updating the NFT's metadata. Accompanying documents, like organic certification PDFs, are stored on IPFS, with their content identifiers (CIDs) saved on-chain. An oracle could attest to temperature data from the shipping container. The end architecture provides a cryptographically verifiable story for the end-consumer to scan and trust.

step-1-iot-data-capture
HARDWARE INTEGRATION

Step 1: Integrating IoT Sensors for Data Capture

The foundation of a verifiable supply chain is immutable data. This step details how to connect physical assets to the blockchain by selecting and configuring IoT sensors to capture critical provenance events.

IoT sensors act as the oracles for your blockchain system, translating real-world events into tamper-proof digital records. For supply chain provenance, key data points include geolocation (GPS modules), temperature/humidity (for perishables), shock/vibration (for fragile goods), and RFID/NFC scans at checkpoints. Selecting the right hardware depends on your asset type: a pharmaceutical shipment requires continuous temperature logging, while high-value electronics need tamper-evident seals. The sensor's job is to generate a cryptographically signed data packet containing the measurement, a timestamp, and a unique device ID.

To prepare sensor data for the blockchain, you must implement a gateway or middleware layer. This component, often a Raspberry Pi or industrial IoT gateway, aggregates data from multiple sensors, formats it into a standard schema (like JSON), and signs it with a private key. This signature is crucial for establishing data integrity off-chain. For example, a temperature reading payload might look like: {"deviceId": "sensor-xyz-789", "timestamp": 1710864000, "temp_celsius": 4.2, "signature": "0xabcd..."}. This structured data is then ready to be submitted as a transaction to a smart contract.

The final integration involves writing the sensor data to your chosen blockchain. You will call a function in your provenance smart contract, such as recordCheckpoint(uint256 shipmentId, string memory sensorData, bytes memory signature). This transaction permanently logs the event on-chain. For cost-efficient and scalable logging, consider using Layer 2 solutions like Polygon or data availability layers like Celestia for high-frequency sensor data, saving the most critical attestations (like custody transfers or quality seals) to a mainnet like Ethereum. This creates an immutable, auditable trail from the physical sensor to the blockchain ledger.

step-2-gs1-data-schema
DATA STANDARDIZATION

Step 2: Defining Standardized Data with GS1 Schemas

Learn how to translate real-world supply chain events into a structured, machine-readable format using the global GS1 standard, creating the foundation for interoperable blockchain records.

A blockchain is only as useful as the data it records. For supply chain provenance, this data must be structured, globally recognized, and unambiguous. This is where the GS1 system comes in. GS1 is a non-profit organization that develops and maintains the world's most widely used supply chain standards, including the barcodes on consumer products. Its core data model, the GS1 Digital Link, provides a standardized vocabulary for identifying physical items (using a Global Trade Item Number or GTIN), logistic units (Serial Shipping Container Code or SSCC), locations (Global Location Number or GLN), and more.

In a blockchain context, you don't store the entire GS1 standard on-chain. Instead, you use it to define the schema for your smart contract events and data structures. For example, a ShipmentReceived event on your provenance smart contract would not just log "Product X arrived." It would log a structured payload referencing standardized identifiers: the GLN of the receiving warehouse, the SSCC of the pallet, and an array of the GTIN + serial numbers for the individual cases. This transforms subjective descriptions into verifiable, queryable data points.

Implementing this starts with your smart contract design. Define your data structures using the GS1 key identifiers as a guide. A Product struct might store a bytes32 hash of the GTIN and batch/lot number. An event for a transformation step, like PackedIntoCrate, would emit the input GTINs and the output SSCC. Using libraries like OpenZeppelin's Strings library can help manage and concatenate these identifiers off-chain before hashing or storing them. The goal is to ensure every on-chain record can be mapped directly back to a physical object or location in the GS1 ecosystem.

The major benefit of this approach is interoperability. A logistics partner, retailer, or regulator can read events from your blockchain and, using the public GS1 standards, immediately understand the data without needing your proprietary documentation. It also future-proofs your system, as GS1 identifiers are designed to be unique and persistent. When selecting which GS1 keys to use, common choices include GTIN (trade items), GLN (locations), SSCC (logistical units), and LOT (batch numbers) for traceability.

To put this into practice, begin by modeling your specific supply chain flow as a series of discrete events (e.g., Manufacture, Aggregate, Ship, Receive, Sell). For each event, document the GS1 identifiers that act as the subject and object. This mapping becomes your implementation blueprint. Resources like the GS1 Digital Link Standard and toolkits from organizations like the Trusted IoT Alliance provide concrete examples for encoding this data for blockchain use, often using URIs or specific JSON-LD contexts.

step-3-smart-contract-design
SUPPLY CHAIN PROVENANCE

Step 3: Designing Smart Contracts for State Transitions

This guide details the core smart contract design for a blockchain-based supply chain, focusing on modeling assets and enforcing state transitions to ensure data integrity.

The core of a supply chain provenance system is a state machine enforced by smart contracts. Each physical item is represented as a non-fungible token (NFT) or a unique identifier in a struct, with its lifecycle defined by a series of permissible state changes. Common states include Manufactured, Shipped, Received, InRetail, and Sold. The contract's primary function is to validate and record transitions between these states, ensuring an immutable and verifiable history. This prevents fraudulent updates, such as marking an item as received before it was shipped.

We define a Product struct to encapsulate the asset's data and state. A mapping from a unique productId (like a serial number) to a Product acts as the system's ledger. The Product struct should contain fields for currentState, metadataURI (pointing to off-chain details like certificates), currentOwner (an Ethereum address), and a history array to log all past transitions. The currentState is typically an enum or uint8 for gas efficiency, defining all possible lifecycle stages.

State transitions are executed via functions like shipProduct(uint256 productId, address to). This function must include access control (e.g., only the current owner can ship) and business logic validation (e.g., require(product.currentState == State.Manufactured)). Upon successful validation, the function updates the currentState to Shipped, changes the currentOwner to the recipient's address, and pushes a new TransitionRecord into the history array. This record should include a timestamp, the new state, and the actor's address, creating a permanent audit trail.

For complex supply chains with multiple participants, consider a role-based access control (RBAC) system. You can implement this using OpenZeppelin's AccessControl contract. Define roles like MANUFACTURER_ROLE, LOGISTICS_ROLE, and RETAILER_ROLE. Your state transition functions would then use modifiers like onlyRole(LOGISTICS_ROLE) to ensure only authorized entities can perform specific actions, such as updating a product's location or confirming receipt. This granular control is critical for enterprise applications.

A key design decision is balancing on-chain and off-chain data. Storing extensive data like high-resolution images or full inspection reports directly on-chain is prohibitively expensive. The standard pattern is to store a hash of the data (or a URI like an IPFS CID) in the metadataURI field. The integrity is guaranteed because the hash is immutable on-chain; if the off-chain data is altered, the hash will not match. Tools like the IPFS protocol or decentralized storage services like Filecoin are commonly used for this purpose.

Finally, your contract should include view functions to allow anyone to verify a product's provenance. A function like getProductHistory(uint256 productId) public view returns (TransitionRecord[] memory) enables downstream consumers, regulators, or end-customers to query the complete, tamper-proof journey of an item. By publishing your contract on a public blockchain like Ethereum, Polygon, or a dedicated enterprise chain, you create a single source of truth that all supply chain partners can trust without relying on a central authority.

TECHNICAL SELECTION

Blockchain Platform Comparison for Supply Chain Provenance

Key architectural and operational differences between leading enterprise blockchain platforms for building a supply chain provenance system.

Core Feature / MetricHyperledger FabricEthereum (L2 / Private)VeChainThor

Consensus Mechanism

Pluggable (e.g., Raft, Kafka)

Proof-of-Stake (Public) / IBFT (Private)

Proof-of-Authority (PoA 2.0)

Transaction Finality

< 1 second

~12 sec (Mainnet) / ~2 sec (Private)

~10 seconds

Native Token Required for Fees

Permissioning Model

Private & Permissioned

Public or Permissioned

Public, Permissioned Delegates

Smart Contract Language

Go, Java, Node.js

Solidity, Vyper

Solidity (VIP-180/181 extensions)

Transaction Cost (Estimate)

Network-defined

$0.50 - $5.00 (L2)

$0.001 - $0.01

Built-in Supply Chain Features

Custom Channels for Data Privacy

Requires custom development

VIP-181 (NFT), Proof-of-Authority tracking

Primary Governance

Linux Foundation Consortium

Decentralized / Consortium

Steering Committee & Authority Masternodes

step-4-building-interfaces
FRONTEND DEVELOPMENT

Step 4: Building User Interfaces for Stakeholders

This guide details how to build intuitive web interfaces that allow different stakeholders—manufacturers, distributors, retailers, and consumers—to interact with your blockchain-based supply chain provenance system.

The frontend application serves as the primary access point for all system users. Its core function is to query the blockchain for product data and submit new provenance events. You will need to integrate a Web3 provider library like ethers.js or web3.js to connect to the blockchain. The application must be able to read from your deployed SupplyChain smart contract using its ABI and address, and write transactions when users with the correct permissions (e.g., MANUFACTURER_ROLE) call functions like addProvenanceRecord. A key initial step is detecting the user's wallet (e.g., MetaMask) and connecting to the correct network, such as a Sepolia testnet or Polygon mainnet.

User experience must be tailored to different stakeholder roles. A manufacturer's dashboard should prominently feature forms to register new products (registerItem) and add the first provenance record. A distributor or retailer interface needs a simple way to scan a product's QR code (which encodes its itemId) and call transferItem to update its custody, followed by addProvenanceRecord to log the handoff. For all roles, displaying the item's full provenance history is critical. This involves calling the getProvenanceHistory view function and rendering a chronological timeline of events, including timestamps, locations, and acting parties.

The most public-facing component is the consumer verification portal. This is often a simple, standalone web page or a module embedded in a retailer's site. A consumer scans a product's QR code, and the frontend fetches and displays the immutable history from the blockchain. This interface should highlight key authenticity signals and present the data in a clean, trustworthy format. To optimize performance and cost, consider using a The Graph subgraph to index your contract's events. This allows your frontend to query provenance history via fast GraphQL APIs instead of making multiple direct RPC calls to the blockchain.

State management is crucial for handling asynchronous blockchain interactions and wallet state. Libraries like React Query or SWR are excellent for caching the results of read calls (e.g., item details). For managing connection state, wallet address, and network ID, use a context provider or a library like wagmi. Always implement clear loading states, transaction receipt feedback, and error handling for failed transactions (e.g., user rejects the transaction or has insufficient gas). Security-wise, never expose private keys in the frontend code; all transactions must be signed by the user's connected wallet.

For deployment, you can host the static frontend on services like Vercel, Netlify, or IPFS (for decentralization). Ensure your application's configuration, such as the smart contract address and RPC endpoint, is easily adjustable via environment variables. Finally, conduct thorough testing with real wallets on a testnet. Simulate the journey of each stakeholder type to ensure the interface is intuitive and the blockchain interactions are reliable before launching on a production network like Polygon or Arbitrum.

How to Build a Blockchain Supply Chain Provenance System | ChainScore Guides