Contracts
Device Pass contract
The device_pass Move package: one soulbound pass per attested device, claims and rebinds signed by Rare's attestor, the registry, events and error codes.
The device_pass package gives each attested device one soulbound pass. Rare's attestor checks a device's TPM off chain (the EK certificate chain, credential activation, and a PCR quote against firmware and boot allowlists) and signs a claim for the holder. The registry is keyed by the device's Rare-salted EK hash, so each device has exactly one current pass. The package is a single module and depends only on the Sui framework.
Published on mainnet with the attestor key set. No device has claimed a pass yet.
0xe81e2d12a766b56a9dae5cb33afc4216bd4ef1fea05f2dd1983de9cd6efc4a650xd4724780ef48b31ec8f3a60c8b3a451df8265475b209af261c6776be5af35ca9On this page, PACKAGE_ID is the package id, REGISTRY_ID is the shared Registry and 0x6 is the Clock.
Modules
Shared objects and caps
Pass numbers run from 1 to count, in the order devices are first claimed.
How a pass follows the device
When a device changes hands, the new owner re-attests it and the attestor signs a rebind with seq set to the record's seq + 1. The device then points at the new holder's new pass, which keeps the device's number, model and first-seen date. The old pass stays in the old wallet but is no longer current (is_current returns false). A pass can't be farmed or sold apart from its device.
Claim
public fun claim(
reg: &mut Registry,
device: vector<u8>,
model: String,
first_seen_ms: u64,
seq: u64,
expires_ms: u64,
signature: vector<u8>,
clock: &Clock,
ctx: &mut TxContext,
): IDMints a pass to the sender and returns its id. The sender must be the holder the attestor signed for. Anyone can pay the gas, so sponsored transactions work. Checks, in order:
- The registry is current (
1), not paused (2), and has an attestor key (4). clock < expires_ms(5).- The ed25519 signature is valid for the sender (
6). deviceis 32 bytes (10) andmodelis at most 64 bytes (11).- First claim: the device has no record and
seqis 0 (8). A second first claim for the same device aborts with7. - Rebind:
seqis the record'sseq + 1(8), and the sender differs from the current holder (9). The new pass takes the number, model and first-seen date from the record.
The registry record then points at the new pass, PassClaimed is emitted and the pass goes to the sender.
Claim message
The attestor signs these raw bytes with ed25519 (no hashing, 64-byte signature):
"RARE_DEVICE_V1" || registry id (32) || holder (32) || device (32) || seq (u64 LE) || first_seen_ms (u64 LE) || expires_ms (u64 LE) || model (UTF-8, the rest)claim_message(registry, holder, device, model, first_seen_ms, seq, expires_ms) returns the same bytes on chain. The registry id ties each signature to one deployment, so a testnet claim never works on mainnet.
Burn
public fun burn(reg: &mut Registry, pass: DevicePass, ctx: &TxContext)The holder destroys their pass. If it was the device's current pass, the record keeps its number, first-seen date and seq with holder set to @0x0, and only a rebind can give the device a new pass. Burning an old, non-current pass leaves the record alone.
Admin calls
These take the AdminCap.
public fun set_issuer_key(_: &AdminCap, reg: &mut Registry, public_key: vector<u8>)
public fun set_paused(_: &AdminCap, reg: &mut Registry, paused: bool)
public fun migrate(_: &AdminCap, reg: &mut Registry)set_issuer_keysets or rotates the attestor key (32 bytes, or empty to close claims;3otherwise). The old key stops working in the same transaction.set_pausedstops every claim and rebind while true. Existing passes are untouched.migratemoves the registry to a new package version after an upgrade (12if it is not newer).
Views
- Registry:
is_claimed(reg, device),record(reg, device),count,issuer_key,paused,is_current(reg, pass) - Record:
record_number,record_holder,record_pass,record_seq,record_first_seen_ms - Pass:
number,model,first_seen_ms,claimed_ms,device,pass_registry
Holders can be listed from the devices table or from PassClaimed events.
Display
name (Rare Device Pass #{number}), description, image_url and thumbnail_url (https://rare.market/device-pass.svg), project_url (https://rare.market), creator (Rare), model, number, first_seen_ms.
Fees
The package charges no fees. Claims cost gas only, and anyone can pay it.
