← Return to the register

Public protocol · v1.0

The Protocol.

The Quire protocol is a small set of public smart contracts. The credential, the vouching gate, and the signing service all live there, not in a database we control. The site you are reading is one possible UI on top of the protocol. Anyone may build another. This page is the canonical reference.

§ I · The credentialCTOID

Soulbound ERC-721, peer-issued.

Contract
0x0e267856F568459BB60dbd1782052207433259CD
Network
Base (8453)
Standard
ERC-721 · non-transferable
Supply
No on-chain cap
§ II · The signing serviceAuthorship

Cryptographic attribution, gated by the credential.

Contract
0x9C4459BdAE61540CE796FA3a5f6E6a1C41f6a787
Hashing convention
keccak256(UTF-8 bytes of content)
Gated by
CTOID.tokenIdOf(msg.sender) > 0
Idempotency
One signature per (Nº, hash). Multi-signer per hash.

A signature binds (tokenId, contentHash, url, title, signedAt). The signer is the wallet that holds the Quire credential. The signature is permanent. There is no unsign function by design.

§ III · VerifyingWithout us

Confirm a credential, confirm a signature.

Is this address a CTO?

bash
cast call 0x0e267856F568459BB60dbd1782052207433259CD \
  "tokenIdOf(address)(uint256)" \
  <wallet-address> \
  --rpc-url https://mainnet.base.org

Returns the Quire Nº as a uint, or 0 if the wallet holds none.

Who signed this content?

bash
# 1. Hash the content (UTF-8 bytes, keccak256)
HASH=$(cast keccak "$(cat article.md)")

# 2. Read every signature attached to that hash
cast call 0x9C4459BdAE61540CE796FA3a5f6E6a1C41f6a787 \
  "signaturesFor(bytes32)((uint256,uint64,string,string)[])" \
  $HASH --rpc-url https://mainnet.base.org

Returns an array of (tokenId, signedAt, url, title) tuples, one per signer. Empty array means the content was never signed by anyone holding a Quire credential.

Same thing, in TypeScript with viem

ts
import { createPublicClient, http, keccak256, toBytes } from "viem";
import { base } from "viem/chains";

const client = createPublicClient({ chain: base, transport: http("https://mainnet.base.org") });
const contentHash = keccak256(toBytes(articleText));

const sigs = await client.readContract({
  address: "0x9C4459BdAE61540CE796FA3a5f6E6a1C41f6a787",
  abi: AUTHORSHIP_ABI,
  functionName: "signaturesFor",
  args: [contentHash],
});

// sigs is an array of { tokenId, signedAt, url, title }
// If sigs.length > 0, the content was signed by a peer-vetted CTO via Quire.
§ IV · SovereigntyBinding commitments

What we have given up.

  1. 01 · No revocation

    The contract exposes lockBurn(), a one-way owner-only function that permanently disables the burn mechanism. The founder will call it before transferring ownership at Nº 0050. After that point no Nº can ever be revoked, not by the founder, not by the multisig, not by anyone. The commitment becomes cryptographic. Until lockBurn() is called, any burn is on chain and visible to all.

  2. 02 · Ownership transfer at Nº 0050

    Once the founding cohort is closed (Nº 0049 issued), administrative ownership of the CTOID contract migrates from the founder to a multisig drawn from the registry. The founder will hold no more authority over the protocol than any other holder.

  3. 03 · Stable convention

    The hashing convention (keccak256 of UTF-8 bytes) will not change. Signatures made today will be verifiable, in the same way, forever.

  4. 04 · Open source

    The Credential contract, the Authorship contract, and the verifier SDK are MIT-licensed. You may read, audit, fork, or run your own deployment without permission.

  5. 05 · Not the canonical view

    This website is one possible UI. The chain is the canonical view. If we go dormant, shut down, or get acquired by a stranger, every existing credential and every existing signature remains verifiable by anyone with the contract address and a Base RPC.

§ V · BuildPublic good

Build your own verifier.

You need three things: the contract address, the ABI (extractable from the deployed bytecode via Etherscan, or copied from the open-source repo), and a Base RPC endpoint. That is the full dependency list. We are not in it.

If you build a competing verifier, a citation tool, a browser extension, an attribution layer for an AI assistant — that is good and we encourage it. The credential is not ours to lock behind a UI.

§ VI · The APINo auth · CORS open

A JSON path, for the impatient.

If hitting the chain yourself is overkill for your use case, we serve a small public JSON API that reads from the same contracts. No auth, no rate limits beyond the reasonable, permissive CORS. All endpoints are GET. Designed for AI assistants, citation tools, browser extensions, and humans with curl. If our site goes down, fall back to §III.

GET/api/work/{hash}

Every signature attached to a content hash.

Request
curl https://quire.cx/api/work/0xfae6...ccef
Response
{
  "hash": "0xfae6...ccef",
  "count": 1,
  "signatures": [
    {
      "tokenId": 1,
      "displayId": "Quire Nº 0001",
      "signedAt": "2026-06-21T16:43:35.000Z",
      "signedAtUnix": 1782060215,
      "url": "https://example.com/article",
      "title": "On boring engineering"
    }
  ]
}
GET/api/cto/{n}

Basic info about a holder: wallet, cohort, profile URL.

Request
curl https://quire.cx/api/cto/1
Response
{
  "tokenId": 1,
  "displayId": "Quire Nº 0001",
  "address": "0xf39F...92266",
  "cohort": "founding",
  "profileUrl": "https://quire.cx/1"
}
GET/api/cto/{n}/works

Every work signed by a given Nº, newest first.

Request
curl https://quire.cx/api/cto/1/works
Response
{
  "tokenId": 1,
  "displayId": "Quire Nº 0001",
  "count": 2,
  "works": [
    { "hash": "0xfae6...", "title": "...", "url": "...", "signedAt": "...", "signedAtUnix": ... }
  ]
}
GET/api/recent?limit=N

Latest signatures across all holders. Default limit 20, max 100.

Request
curl https://quire.cx/api/recent?limit=5
Response
{
  "count": 5,
  "signatures": [
    { "tokenId": 1, "displayId": "Quire Nº 0001", "hash": "...", "title": "...", "url": "...", "signedAt": "...", "signedAtUnix": ... }
  ]
}
Quire · the peer-vetted register of CTOs