SPCR Documentation

If SPCR disappeared

Your receivables are not stored in SPCR. They are records on a public blockchain, and SPCR is one way to read and write that record rather than the place it lives. If SPCR were switched off tomorrow, every certificate would still exist, still be owned by the same address, and still be readable by anyone.

What the blockchain will not tell you is which loan is which. A certificate's identifier is a hash, so you cannot work back from a certificate to a Loan ID; you compute it in the other direction, from data you hold. Continuity therefore depends on you holding that data.

Keep your own copy of your Loan IDs and pool passkeys. It is the only thing on this page that needs anything from you.

An identifier is SHA-256( UPPERCASE(TRIM(Loan ID)) + "|" + pool passkey ). With the Loan IDs and the passkey you can compute every identifier in a pool and find it on chain unaided. Without the passkey you cannot, and the chain will not give it back to you.

The loan tape offered after each registration contains both. Save it.

What you need, and where it is

Where it lives Survives SPCR
The identifier and its current owner The blockchain Yes
The transfer history The blockchain Yes
Loan IDs, pools and passkeys SPCR's database, and your own records Only if you hold a copy

The last row is the whole of your exposure. See What SPCR knows for the complete picture of what is held where.

The contract

The details below are read from the deployment serving this page, so they follow the live configuration rather than being typed into a document that would go stale the day the contract moves.

These are the Sepolia details, which is a test network. A production deployment is its own contract, at its own address, on its own chain. This table follows whichever deployment is live, so check it again rather than writing these values down.

Chain
Sepolia (chain ID 11155111)
Contract
0x1e6e275245a17504f9a3054cf7717b4e19de00f8
Standard
ERC-721. Verifiable on chain: supportsInterface(0x80ac58cd) is true, 0xd9b67a26 (ERC-1155) is false
Name / symbol
SPCR Certificate / SPCR
Metadata
None. tokenURI always returns ""
Explorer
Etherscan

The batch functions are named and shaped like ERC-1155 (mintBatch, safeBatchTransferFrom, with amounts and uris parameters) even though this is an ERC-721 contract. They match the call shape of the custody provider's own token template, so the custody service can point at this contract by changing an address rather than its code. amounts must be 1 for every entry and uris must be empty; anything else reverts.

Reading it

Standard ERC-721, so any tool works: a block explorer, any Ethereum library, any public RPC endpoint.

Function Answers
ownerOf(uint256 tokenId) Which address holds this receivable now. Reverts if it was never registered.
balanceOf(address owner) How many certificates an address holds.
supportsInterface(bytes4) Interface support, as above.

Two events give you the full history:

  • CertificateRegistered(uint256 indexed tokenId, address indexed holder) on registration.
  • The standard ERC-721 Transfer(address indexed from, address indexed to, uint256 indexed tokenId) on every move, including the mint.

Because tokenId is indexed on both, you can pull the entire life of one receivable with a single filtered log query and no access to anything of ours.

Writing to it

This is the part that decides whether you are self-sufficient.

Function Who may call it
transferFrom / safeTransferFrom The holder, or an operator the holder approved. Standard ERC-721.
safeBatchTransferFrom(from, to, ids[], amounts[], data) Same. Moves a pool as one transaction.
setApprovalForAll(operator, bool) The holder, to delegate moving its certificates.
mint / mintBatch MINTER_ROLE only. Registration is STOKR-only, permanently.

Transfers are not role-gated. There is no privileged path by which STOKR can move a certificate you hold. Authorisation is the ERC-721 standard: you, or an operator you approved with setApprovalForAll. This was verified against the deployed contract, including that MINTER_ROLE does not permit moving another holder's token.

If you control the address, you can move your certificates with or without us, using any Ethereum tooling, for as long as the chain exists.

Two roles exist and neither can take your certificates:

  • MINTER_ROLE registers new certificates. Held by STOKR's custody vault and operator.
  • DEFAULT_ADMIN_ROLE grants and revokes MINTER_ROLE. Nothing more. The deploying key renounced it after setup, which is verifiable on chain.

Finding your receivables without SPCR

  1. Take your Loan IDs and the pool passkey from your own records.
  2. Compute each identifier. Uppercase the Loan ID, trim surrounding whitespace, append |, append the passkey, and SHA-256 the result. The output is the tokenId as a 32-byte hex value.
  3. Convert to decimal if your tool wants a uint256. A block explorer shows the same number in decimal in its Token ID field, which is why SPCR displays both forms.
  4. Call ownerOf with it against the contract above.

On any machine with a shell:

# One receivable's identifier, in hex.
printf '%s|%s' 'YOURCO-2026-P1-L0001' 'your-pool-passkey' | shasum -a 256

That hash is the tokenId. Nothing in that command touches SPCR.

Recovering the certificates themselves

Whether you can move your certificates depends on who holds the key to the address that owns them. Three cases, and they differ substantially.

If STOKR holds custody for you

This is the arrangement where STOKR provisioned your vault and it sits in STOKR's own custody workspace. Be clear about what that means:

You do not hold the key, so this is a release rather than a recovery. You cannot sign the transaction yourself. What exists instead is a defined process for STOKR to move every certificate in your vault to an address you nominate.

The release process

What you can do with no help from anyone, today and in any future, is prove what you own: compute your identifiers, call ownerOf, and read the complete transfer history. That never depends on us. What needs STOKR is signing the transaction that moves it.

How a release runs. On a written request from a signatory you nominated in advance:

  1. We verify the requester out of band, by the channel on file rather than the one the request arrived on. Two staff record it independently.
  2. We verify the destination. Normally the backup address you confirmed at the start, already whitelisted, which is why we ask for it then rather than during an incident. A different destination needs a fresh signature proving you control it. Never an address supplied only in the request. It is read back to you digit by digit.
  3. We build a manifest: every tokenId your vault holds, cross-checked against the chain, with the pool each belongs to. That manifest is what gets approved, and you receive it.
  4. Approval requires more than the operations team. Compliance and a director sign off, because a release is irreversible and moves title out of STOKR's control entirely.
  5. We execute in chunks, confirming settlement and re-reading ownerOf after each one before sending the next, so a partial failure is caught at the time rather than reconciled afterwards.
  6. You get an evidence pack: every tokenId with its transaction hash, and ownerOf output proving your address now holds all of them.

The target is 10 business days from a verified request.

If STOKR itself is gone

A process STOKR runs is no use if STOKR has stopped existing, so that case is covered separately and by someone else.

  • The obligation to release sits in your agreement, survives termination and binds a liquidator, so an insolvency practitioner has an instruction to act on rather than a discretion to exercise.
  • The material needed to recover the custody workspace independently of STOKR is held by a third-party escrow agent, under release conditions that include our insolvency or cessation, and our failure to respond to a valid release request. Ask us who the agent is; if we will not name them, the escrow is worth nothing to you.

Three things to do now, not later

None of these can be arranged during an incident.

  1. Set a backup address and prove you control it. You are asked for one when you choose STOKR custody, so it may already be on file. Then confirm it by signature from Confirm my address in your workspace, and use Set as my backup address on the result. Until it is confirmed it is an address somebody typed, and we will not release to one of those. Once confirmed, STOKR whitelists it in custody so it is in place before anybody needs it.
  2. Confirm your signatories. Two named people with a contact channel each, refreshed annually. This is what stops a forged request from working.
  3. Keep the data package. Pools, passkeys, Loan IDs and identifiers. A vault full of certificates you cannot map back to loans is a poor outcome, and this is the only part we hold that you cannot rebuild from the chain.

Or remove the problem entirely

Move to your own custody and this section stops applying to you. Your certificates sit at an address you control and the next section is your procedure.

If you have your own Fireblocks workspace

You control the vault and therefore the certificates. Nothing here depends on SPCR continuing to exist.

  1. Confirm the address. Your workspace's vault address is the to on the registration transactions and the current ownerOf answer.
  2. Reach the contract from Fireblocks. Use your workspace's contract interaction or dApp connection to the contract address above, on the right chain. Because the contract is not currently verified on the public explorer, have the ABI to hand. The function signatures on this page are the complete set you need.
  3. Move them. safeTransferFrom(from, to, tokenId) for one, or safeBatchTransferFrom(from, to, ids[], amounts[], data) for a pool, with every entry in amounts set to 1.
  4. Approve your own policy. The transaction goes through your workspace's normal transaction policy, not ours.

If you have your own other custody

Any address you control works the same way: a self-custodied key, a multisig such as Safe, or another custodian that can sign an arbitrary contract call.

  1. Compute your identifiers as above and confirm ownerOf returns your address.
  2. Call transferFrom or safeTransferFrom from whatever tooling your custody supports. If it can sign an Ethereum contract call, it can do this.
  3. If you use a smart-contract wallet, note that safeTransferFrom invokes the recipient's onERC721Received hook. Sending to a contract that does not implement it reverts, which is the standard protecting you from sending a certificate somewhere it can never leave. Use transferFrom only if you understand that consequence.

What an SPCR API would and would not do for this

An API served by SPCR cannot be part of a plan for SPCR being unavailable: it is the same infrastructure and would be gone at the same time.

Everything on this page runs on a public blockchain and a hashing function you can execute offline. An API is worth having for automation and integration, but a continuity plan that depended on one would not be a continuity plan.