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
StateCodeDescriptionAllowed transitions
NONE0Asset does not exist→ MINTED
MINTED1NFT created, metadata stored→ BOUND, RECYCLED (void)
BOUND2NFC tag cryptographically linked→ ACTIVATED, FLAGGED, RECYCLED
ACTIVATED3QA passed, available for sale→ CLAIMED, FLAGGED, RECYCLED
CLAIMED4Consumer owns the asset→ CLAIMED (resale), FLAGGED, RECYCLED
FLAGGED5Lost, stolen, or recalled — under investigation→ pre-flag state (resolve), RECYCLED
RECYCLED6End of life, tag decommissionedTerminal

Transition table

FromFunctionToAuthorized caller
NONEmint()MINTEDManufacturer — CAP_MINT
MINTEDbindTag()BOUNDManufacturer — CAP_BIND
BOUNDactivate()ACTIVATEDDistributor, QA inspector, or retailer — CAP_ACTIVATE
ACTIVATEDclaim()CLAIMEDRetailer on behalf of the buyer, or consumer directly
CLAIMEDtransferAsset()CLAIMEDCurrent owner — sanctioned secondary-market resale
BOUND / ACTIVATED / CLAIMEDflag()FLAGGEDOwner, manufacturer (recall), or law enforcement — CAP_FLAG
FLAGGEDresolve()Exact pre-flag stateArbitrator or DAO
Any live staterecycle()RECYCLEDOwner or authorized recycler
Flag and resolve semantics. 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:

ActorMintBindActivateClaimFlagResolveRecycle
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.

SignalWeightWhat it checks
NFC tag UID30AES-128 + SUN MAC cryptographic authentication of the NTAG 424 DNA chip
Owner wallet25On-chain ERC-721 ownership matches the presenting wallet
Lifecycle state20State and full transition history are valid for the claimed asset
Geolocation15Geographic plausibility versus previous scans
Timestamp10Temporal 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.

  1. Consumer taps the NFC tag with a phone.
  2. 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.
  3. 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.
  4. The gateway performs the on-chain lookup on Base Sepolia: asset state, ownership, and transition history from TAGITCore.
  5. The 5-signal verification pipeline runs and aggregates the weights.
  6. Result: a confidence score (0–100) and a verdict returned to the scanner.

Error codes

CodeNameDescription
E001InvalidStateAsset not in the required state for this operation
E002UnauthorizedCaller lacks the required capability badge
E003TagAlreadyBoundTag hash has already been used
E004InvalidSignatureNFC signature verification failed
E005QuarantineActiveAsset is under an active recovery investigation

Next steps