Protocol
Asset Lifecycle
Every physical product authenticated by TAG IT follows a deterministic 7-state lifecycle enforced on-chain. The digital twin is an ERC-721 token in TAGITCore; every transition is validated by LifecycleLib, gated by a BIDGES capability badge, and emitted as an indexable event. The state machine runs on Base Sepolia today (chain ID 84532).
The seven states
[0] NONE ──mint()──▶ [1] MINTED ──bindTag()──▶ [2] BOUND ──activate()──▶ [3] ACTIVATED
│
claim()
│
▼
[6] RECYCLED ◀──recycle()── (any live state) [4] CLAIMED ⟲ transferAsset()
│
flag() from BOUND / ACTIVATED / CLAIMED ──▶ [5] FLAGGED
resolve() restores exact pre-flag state| State | Code | Description | Allowed transitions |
|---|---|---|---|
NONE | 0 | Asset does not exist | → MINTED |
MINTED | 1 | NFT created, metadata stored | → BOUND, RECYCLED (void) |
BOUND | 2 | NFC tag cryptographically linked | → ACTIVATED, FLAGGED, RECYCLED |
ACTIVATED | 3 | QA passed, available for sale | → CLAIMED, FLAGGED, RECYCLED |
CLAIMED | 4 | Consumer owns the asset | → CLAIMED (resale), FLAGGED, RECYCLED |
FLAGGED | 5 | Lost, stolen, or recalled — under investigation | → pre-flag state (resolve), RECYCLED |
RECYCLED | 6 | End of life, tag decommissioned | Terminal |
Transition table
| From | Function | To | Authorized caller |
|---|---|---|---|
| NONE | mint() | MINTED | Manufacturer — CAP_MINT |
| MINTED | bindTag() | BOUND | Manufacturer — CAP_BIND |
| BOUND | activate() | ACTIVATED | Distributor, QA inspector, or retailer — CAP_ACTIVATE |
| ACTIVATED | claim() | CLAIMED | Retailer on behalf of the buyer, or consumer directly |
| CLAIMED | transferAsset() | CLAIMED | Current owner — sanctioned secondary-market resale |
| BOUND / ACTIVATED / CLAIMED | flag() | FLAGGED | Owner, manufacturer (recall), or law enforcement — CAP_FLAG |
| FLAGGED | resolve() | Exact pre-flag state | Arbitrator or DAO |
| Any live state | recycle() | RECYCLED | Owner or authorized recycler |
flag() is valid from any state with a bound tag — BOUND, ACTIVATED, or CLAIMED — covering manufacturer recall, pre-sale theft, and consumer lost/stolen reports. resolve() restores the exact state the asset held before it was flagged; it is not a one-way trip to CLAIMED, so a recall or recovery can never be used to skip a forward step. recycle() (void, scrap, end-of-life) is valid from any live state and is terminal. transferAsset() is the sanctioned secondary-market resale path and keeps the asset in CLAIMED.Function reference
The core lifecycle surface of TAGITCore. Gas figures are approximate Base Sepolia estimates.
// NONE → MINTED · ~135k gas · CAP_MINT
function mint(string calldata productId, string calldata sku,
bytes32 metadataHash, string calldata metadataURI)
external returns (uint256 tokenId);
// MINTED → BOUND · ~191k gas · CAP_BIND
// tagHash must be globally unique; signature must validate against the tag key
function bindTag(uint256 tokenId, bytes32 tagHash, bytes calldata signature) external;
// BOUND → ACTIVATED · ~198k gas · CAP_ACTIVATE
function activate(uint256 tokenId, bytes calldata qaSignature) external;
// ACTIVATED → CLAIMED · ~217k gas
function claim(uint256 tokenId, address newOwner, bytes calldata proofOfPurchase) external;
// BOUND | ACTIVATED | CLAIMED → FLAGGED · ~225k gas · CAP_FLAG
function flag(uint256 tokenId, FlagReason reason, bytes calldata evidence) external;
enum FlagReason { LOST, STOLEN, COUNTERFEIT_SUSPECTED, RECALL, CUSTOMS_HOLD }
// FLAGGED → exact pre-flag state · ~244k gas · arbitrator / DAO
function resolve(uint256 tokenId, Resolution resolution, address newOwner) external;
// any live state → RECYCLED (terminal) · ~225k gas
// marks the tag hash as spent — it can never be rebound
function recycle(uint256 tokenId, bytes calldata recycleProof) external;Actor permission matrix
Capabilities are granted per role through BIDGES. Standard assignments for supply-chain actors:
| Actor | Mint | Bind | Activate | Claim | Flag | Resolve | Recycle |
|---|---|---|---|---|---|---|---|
| Manufacturer | ✓ | ✓ | — | — | ✓ (recall) | — | — |
| Distributor | — | — | ✓ | — | — | — | — |
| Retailer | — | — | ✓ | ✓ (point of sale) | — | — | — |
| Consumer (owner) | — | — | — | ✓ | ✓ | — | — |
| Inspector | — | — | — | — | ✓ | — | — |
| Gov / Military & law enforcement | — | — | — | — | ✓ | — | — |
| Arbitrator | — | — | — | — | — | ✓ | — |
| Recycler | — | — | — | — | — | — | ✓ |
| Admin / DAO | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
transferAsset() is gated by current ownership rather than a capability badge — any owner in CLAIMED state can resell. Gov / Military and law-enforcement actors hold the GOV_MIL (20) and LAW_ENFORCEMENT (21) identity badges and exercise flag authority for customs holds and stolen-goods interdiction.
Business rules
- One tag, one token — a tag hash can only ever be bound once; recycling marks it as spent permanently.
- Forward only — transitions are irreversible, with the single exception of
resolve()restoring the pre-flag state. - Capability required — every state-changing function checks a BIDGES badge or ownership before executing.
- Event trail — every transition emits an indexable event, queryable through the Goldsky subgraph.
Verification signals
Every scan runs a 5-signal weighted verification pipeline. Each signal contributes its weight to a confidence score from 0 to 100; failed or inconsistent signals subtract their weight and raise the risk score. The verdict — authentic, caution, or flag-for-review — follows from the aggregate, so a cloned tag with a valid-looking UID still fails when ownership, state history, or geography disagree.
| Signal | Weight | What it checks |
|---|---|---|
| NFC tag UID | 30 | AES-128 + SUN MAC cryptographic authentication of the NTAG 424 DNA chip |
| Owner wallet | 25 | On-chain ERC-721 ownership matches the presenting wallet |
| Lifecycle state | 20 | State and full transition history are valid for the claimed asset |
| Geolocation | 15 | Geographic plausibility versus previous scans |
| Timestamp | 10 | Temporal consistency — no impossible travel or replayed reads |
NFC authentication flow
Authentication is challenge–response in nature: the NTAG 424 DNA never emits a static identifier. Each tap produces a fresh SUN (Secure Unique NFC) cryptogram over the UID and a monotonically increasing tap counter, so a copied read is useless the moment the genuine tag is tapped again.
- Consumer taps the NFC tag with a phone.
- The NTAG 424 DNA increments its tap counter and emits a one-time SUN message: UID + counter + AES-128 CMAC computed with the tag's secret key.
- The phone forwards the cryptogram to the verification gateway, which recomputes the CMAC and rejects any read whose counter does not exceed the last verified value — replays fail here.
- The gateway performs the on-chain lookup on Base Sepolia: asset state, ownership, and transition history from
TAGITCore. - The 5-signal verification pipeline runs and aggregates the weights.
- Result: a confidence score (0–100) and a verdict returned to the scanner.
Error codes
| Code | Name | Description |
|---|---|---|
E001 | InvalidState | Asset not in the required state for this operation |
E002 | Unauthorized | Caller lacks the required capability badge |
E003 | TagAlreadyBound | Tag hash has already been used |
E004 | InvalidSignature | NFC signature verification failed |
E005 | QuarantineActive | Asset is under an active recovery investigation |
Next steps
- Access Control (BIDGES) — the badges that gate each transition
- Smart Contracts —
TAGITCoreand the full 25-contract suite - NFC Hardware — NTAG 424 DNA and the chip tiers above it