Skip to the content
PokedexDocs

Attestation

The program cannot read Collector Crypt's off-chain records, so an attestor key signs a statement about each card, and deposit accepts the card only with that signature. The statement binds the deployment, the card, its class, its record, its cert and an expiry.

On this page

The signed message

The message is 160 bytes.

OffsetSizeField
08Domain CARDPAD1
832Vault config address, so a statement cannot be replayed against another deployment
4032Core asset address
7232class_id
10432json_hash
13616Grader cert number, ASCII, zero padded (truncated to 16 bytes if longer)
1528expires_at, unix seconds, little endian

json_hash is the sha256 of the canonical string company|grade|cert|universal|itemName|metadataUri|insuredValue, built from Collector Crypt's record of the card. The program stores it with the copy. A later check re-reads the record and reports whether it changed since the deposit.

How the program checks it

  1. The instruction before

    The instruction immediately before deposit must be an Ed25519 precompile instruction.

  2. One signature, nothing outside

    It must carry exactly one signature, and its signature, public key and message offsets must all point into its own data.

  3. The right key

    The public key must be the vault config's attestor. Any other key fails with WrongAttestor.

  4. The same deposit

    The signed message must equal the message rebuilt from the deposit's own accounts and arguments, or it fails with AttestationMismatch.

  5. Not expired

    The deposit must land no later than expires_at, or it fails with AttestationExpired.

What the attestor checks before it signs

The attestor service answers POST /attest with the asset and the depositor. It refuses, in this order:

RefusalWhy
400The body is not JSON, or the asset or depositor is not a public key
404The asset is not found
422Not a Metaplex Core asset in a collection
422The asset is owned by someone other than the depositor
422The vault is not initialized, or the collection is not accepted by the vault
422The service's key is not the vault's attestor
422Collector Crypt's record could not be read, or lacks the grader, grade, gemrate id or cert
404No class exists yet for this card's identity

Collector Crypt's record must also name the same asset, and its metadata URI must equal the asset's on-chain URI. A | in any identity field is refused.

On success it returns the identity, class, mint, json_hash, cert, expiry, the 160-byte message and the signature. The statement expires 120 seconds after it is signed, as the service runs.

The rest of this path

Solana mainnet

Written from the protocol, security and card documents of the pokedex repository and from its code (card-vault, card-launch, cp-ix). Every figure on these pages comes from there.

UpDown to moveEnter to open