Development of Blockchain Supply Chain Solution
Before designing a system, honestly answer: why blockchain here? In most corporate supply chain projects the answer turns out unconvincing—"so all participants see one version of data" is solved by ordinary shared database with proper access rights. Blockchain is justified when: participants don't trust each other and don't trust single database operator, need immutable records with verifiable history, smart contracts automate calculations between parties without intermediary. If these conditions are met—proceed.
Architectural Patterns for Supply Chain
Public vs Private Blockchain: Real Tradeoff
Public EVM (Ethereum/Polygon/Arbitrum) means data is public, smart contracts are verifiable by anyone, no need to agree on consensus. Minus: competitive data (cost, volumes, suppliers) becomes public. Solution—store hashes of data on-chain, actual data in encrypted storage.
Hyperledger Fabric is permissioned blockchain, data visible only to channel members. Complex setup, requires dedicated infrastructure, high entry barrier. Justified for enterprise consortiums with clear governance model.
Polygon CDK / OP Stack (private instance) is EVM-compatible L2 with permissioned validator. Compromise: EVM tooling and smart contracts, but control over participant composition. Data can be published to public DA layer (Ethereum, Avail) for verifiability without public content.
For most real supply chain projects—public EVM with sensitive data encryption or Polygon CDK. Hyperledger Fabric if already have enterprise Java team and no plans to integrate with DeFi.
Data Model: What and How to Store On-Chain
Antipattern: store all product data on-chain. Weight of goods, manufacture date, 10,000-record temperature log—all on-chain is expensive and excessive.
Correct approach: on-chain store only anchors and transitions.
Product Identity (NFT) each unit of goods or batch is NFT. ERC-721 for unique units (art, jewelry, expensive equipment), ERC-1155 for batches of interchangeable goods.
struct ProductBatch {
bytes32 batchId;
uint256 productTypeId;
uint256 quantity;
address manufacturer;
uint64 manufacturedAt;
bytes32 certificationHash; // hash of quality certs in IPFS
bytes32 specificationHash; // hash of tech specifications
BatchStatus status;
}
Chain of Custody Events each transfer of rights: manufacturer → warehouse → carrier → customs → distributor → retailer. Each event contains: from, to, timestamp, location hash, condition hash, documents hash.
event CustodyTransferred(
bytes32 indexed batchId,
address indexed from,
address indexed to,
bytes32 locationHash,
bytes32 conditionHash,
bytes32 documentsHash,
uint64 timestamp
);
Milestone Anchoring control points with document hashes. Customs declaration, certificate of origin, inspection report—documents in IPFS/Arweave, hashes in event logs.
Verification of Physical World
Blockchain cannot itself verify that goods match the record. Several mechanisms:
IoT + Oracle sensors (temperature, humidity, GPS) send data via IoT gateway to oracle. Oracle aggregates and records in contract. For cold chain (pharma, food) this is critical.
QR/NFC + mobile app each chain participant scans tag on receipt and transfer. Transaction signed with employee key. Audit trail created from each participant.
Proof of Inspection accredited inspector (natural person) signs inspection report with custodial key. On-chain registry of accredited inspectors with revocation.
ZK-proof for sensitive data supplier wants to prove goods match specification (temperature maintained), not revealing exact values. ZK-proof allows saying "temperature always in 2–8°C range" without publishing exact values. For supply chain used in premium food tracking and pharma.
Smart Contracts: Key Components
Registry Contracts
ParticipantRegistry on-chain registry of supply chain participants with roles: Manufacturer, Carrier, Warehouse, CustomsBroker, Inspector, Retailer. Participant verification via DAO governance or centralized operator (depends on model).
ProductTypeRegistry catalog of product types with validation rules. Quality control parameters for each type: acceptable temperature ranges, humidity, max time in transit.
Supply Chain Contract
contract SupplyChainTracker {
mapping(bytes32 => ProductBatch) public batches;
mapping(bytes32 => CustodyEvent[]) public custodyHistory;
mapping(bytes32 => bytes32[]) public milestones;
function initiateBatch(
bytes32 batchId,
uint256 productTypeId,
uint256 quantity,
bytes32 specificationHash
) external onlyRole(MANUFACTURER_ROLE) {
require(batches[batchId].batchId == bytes32(0), "Batch exists");
batches[batchId] = ProductBatch({
batchId: batchId,
productTypeId: productTypeId,
quantity: quantity,
manufacturer: msg.sender,
manufacturedAt: uint64(block.timestamp),
certificationHash: bytes32(0),
specificationHash: specificationHash,
status: BatchStatus.Created
});
emit BatchInitiated(batchId, msg.sender, productTypeId, quantity);
}
function transferCustody(
bytes32 batchId,
address to,
bytes32 locationHash,
bytes32 conditionHash,
bytes32 documentsHash
) external {
ProductBatch storage batch = batches[batchId];
require(getCurrentCustodian(batchId) == msg.sender, "Not custodian");
require(participantRegistry.isActive(to), "Invalid recipient");
custodyHistory[batchId].push(CustodyEvent({
from: msg.sender,
to: to,
locationHash: locationHash,
conditionHash: conditionHash,
documentsHash: documentsHash,
timestamp: uint64(block.timestamp)
}));
emit CustodyTransferred(batchId, msg.sender, to,
locationHash, conditionHash, documentsHash, uint64(block.timestamp));
}
}
Payment Automation
For automatic calculations between chain participants—escrow with milestone release:
// Pay carrier on confirmed delivery
function confirmDelivery(bytes32 batchId) external {
ShipmentPayment storage payment = payments[batchId];
require(msg.sender == payment.buyer, "Not buyer");
require(getCurrentCustodian(batchId) == payment.buyer, "Not delivered");
uint256 amount = payment.amount;
payment.released = true;
IERC20(payment.token).safeTransfer(payment.carrier, amount);
emit PaymentReleased(batchId, payment.carrier, amount);
}
For complex multi-party calculations (importer pays customs broker, carrier, insurer at different milestones)—composable payment streams via Superfluid or custom escrow with multiple payees.
Integration with Legacy ERP Systems
Real supply chain doesn't start from scratch—there are SAP, Oracle SCM, 1C. Integration:
Event-driven middleware ERP publishes events (goods received, waybill closed) to message bus (Kafka, RabbitMQ). Middleware translates to blockchain transactions. Bidirectional: blockchain events go back to ERP.
API gateway with caching most ERP requests read data, not write. Cache blockchain data in traditional DB for fast queries, sync via events.
Identity mapping ERP uses internal IDs, blockchain uses addresses and hashes. Need mapping table (off-chain, traditional DB) for sync.
Governance and Multisigs
Supply chain consortium requires governance:
- Adding new participant: multisig from existing key participants
- Changing verification rules: timelock + voting
- Emergency pause: 2/3 multisig from core participants
- Dispute resolution: on-chain arbitration or off-chain with on-chain enforcement
Gnosis Safe as basic multisig + Governor contract from OpenZeppelin for voting—standard combination.
Development Phases
| Phase | Content | Duration |
|---|---|---|
| Business analysis | Mapping supply chain processes, participants, data | 2–3 weeks |
| Architecture | Choose network, data model, governance scheme | 2–3 weeks |
| Core contracts | Registry, tracker, payments | 4–6 weeks |
| Oracle & IoT integration | Data pipeline from sensors/ERP | 3–5 weeks |
| Frontend / Mobile | Interface for participants, scanning | 4–6 weeks |
| ERP integration | Middleware, sync | 3–4 weeks |
| Pilot | Limited launch with real participants | 4–8 weeks |
| Production | Full launch | 2–3 weeks |
Realistic timeline from analysis to production—6–10 months. Main risk not in blockchain—in change management: convincing all chain participants to use new system.







