For the complete documentation index, see llms.txt. This page is also available as Markdown.

19. Revoke a claim

Revoking a claim withdraws an attestation. The Claim Issuer does it when the fact it attested is no longer true, or when the claim was issued in error. The effect is immediate and needs no action from any Issuer: from the next eligibility check, the claim stops counting for every asset, and an investor that relied on it alone can no longer receive.

At a glance

Triggered by

Claim Issuer

Actors

Claim Issuer, Investor, Issuer, Platform

Contracts

The ONCHAINID of the Claim Issuer, ERC734Validator, the ONCHAINID of the Investor (when the claim is also removed), TREXRegistry (read only, for the effect)

Preconditions

The claim was issued (see 05); the Claim Issuer controls a MANAGEMENT key of its identity; the Claim Issuer knows the claim: the identity, the topic and the claim data

Result

The claim reads as Revoked, and no asset counts it any longer

Actors and roles

Actor
Role in this flow
What they hold

Claim Issuer

Decides the revocation and submits it.

A MANAGEMENT key of its ONCHAINID

Investor

Is affected: it may no longer be eligible. Does not transact, unless it removes the claim from its identity.

Its ONCHAINID and its positions

Issuer

Is affected: a holder of its asset may have become ineligible. Does not transact in this flow.

The agent operations of its asset

Platform

Computes the digest, relays the call and reports the effect.

Whatever keys the Claim Issuer has authorized

Sequence

Step by step

Step 1. Identify the claim

Who: Platform, on behalf of the Claim Issuer

Call: Off-chain, using read calls

Before the call: The Claim Issuer has decided to withdraw its attestation for an identity and a topic.

What happens: The Platform computes claimId = keccak256(abi.encode(issuer, topic)) and reads getClaim(claimId) on the Investor's identity, which returns the claim as stored: signature and data. It reads getClaimHash(identity, topic, data) on the Claim Issuer's identity, which returns the digest of that claim, and isDigestRevoked(digest), which must be false. A Claim Issuer that stored the digest when it issued the claim skips the first two reads.

What changes: Nothing on-chain.

Step 2. Revoke the claim

Who: Claim Issuer (MANAGEMENT key of its identity)

Call: revokeClaimByDigest(digest), called on the Claim Issuer's ONCHAINID

Before the call: Step 1 is done. The call is made directly on the issuer's identity by the key holder.

What the contract checks:

  1. The caller holds MANAGEMENT on the Claim Issuer's identity. Otherwise the call reverts with SenderDoesNotHaveManagementKey.

  2. The digest is not already revoked. Otherwise ClaimAlreadyRevoked.

What changes: The issuer's identity records the digest as revoked and emits ClaimRevoked(digest, issuer, caller). The claim is still stored on the Investor's identity. From now on, isClaimValid returns false for it and getClaimStatus returns Revoked.

Step 3. Confirm the effect

Who: Platform

Call: Off-chain, using read calls

Before the call: Step 2 is confirmed.

What happens: The Platform reads isClaimValid(identity, topic, signature, data) on the Claim Issuer's identity, which returns false. For each asset concerned, it reads TREXRegistry.isVerified(address) for the Investor's addresses. The result is false when no other valid claim from a trusted issuer covers the topic. The Claim Issuer informs the Investor, and the Issuers it has an agreement with, under its own process.

What changes: Nothing on-chain.

Step 4. Remove the claim from the identity

Optional. It tidies the identity. It is not needed for the revocation to take effect.

Who: Identity Owner (CLAIM_SIGNER key of the Investor's identity), or the Claim Issuer's ONCHAINID if the Claim Issuer has standing in the network

Call: removeClaim(claimId), called on the Investor's ONCHAINID

Before the call: The claim is on the identity.

What the contract checks:

  1. The claim exists on the identity. Otherwise ClaimNotRegistered.

  2. The caller holds CLAIM_SIGNER on the identity. If it does not: the caller is the issuer of this claim, and that issuer is a CLAIM_ISSUER identity with sufficient reputation. Otherwise SenderDoesNotHaveClaimSignerKey, IdentityNotClaimIssuerType or ReputationBelowClaimAddThreshold.

What changes: The claim is deleted from the identity, and its digest is marked as revoked on both sides. The ERC734Validator emits ClaimRemoved.

State after the flow

  • isDigestRevoked(digest) on the Claim Issuer's identity is true.

  • isClaimValid returns false and getClaimStatus returns Revoked for the claim.

  • For every asset that relied on this claim alone for a required topic, TREXRegistry.isVerified is false for every address of the Investor's identity.

  • The Investor's positions are unchanged. It keeps what it holds, cannot receive more, and can still transfer to an eligible recipient.

  • The same signed claim can never be made valid again. To attest the fact again, the Claim Issuer signs a new claim.

  • After step 4, the identity no longer holds the claim.

Failure modes

Symptom
Cause
Fix

Reverts with SenderDoesNotHaveManagementKey

The caller does not hold MANAGEMENT on the issuer's identity, for example it is the signing key (step 2, check 1)

Submit with a MANAGEMENT key

Reverts with ClaimAlreadyRevoked

The digest is already revoked (step 2, check 2)

Nothing to do

The revocation succeeds and the claim still reads Valid

The digest revoked is not the digest of the stored claim: another identity, topic or data was used

Read the stored claim with getClaim, recompute with getClaimHash, revoke that digest

The call is refused when sent as a user operation

revokeClaimByDigest and removeClaim require a direct call from the key holder

Call the identity directly

The claim is revoked and the Investor is still eligible

Another trusted Claim Issuer has a valid claim for the same topic on the identity

Intended. Eligibility needs one valid claim per topic

removeClaim reverts with ClaimNotRegistered

The identity holds no claim with that identifier (step 4, check 1)

Recompute claimId from the issuer and the topic

Many claims must be withdrawn at once

A signing key was compromised

Remove CLAIM_SIGNER from that key (see 22). Every claim it signed stops validating

Common misunderstandings

Wrong: "The Issuer revokes the investor's KYC."

Right: A claim is revoked by the Claim Issuer that signed it. An Issuer can stop trusting a Claim Issuer for its asset, which is a different operation with a different scope: it affects one asset and every investor that relied on that issuer.

Wrong: "After a revocation, someone has to update the token or the registry."

Right: Nothing is updated. The registry asks the Claim Issuer whether each claim is valid at every eligibility check. The revocation is the answer changing.

Wrong: "A revoked claim removes the investor's tokens."

Right: Eligibility is checked on the recipient of a movement. The investor keeps its position, can no longer receive, and can still sell or transfer to an eligible recipient: it was eligible when it received the tokens and it is still identified. An Issuer that wants to block it freezes its tokens or its address.

Wrong: "Revocation removes the claim from the identity."

Right: The claim stays stored and reads as Revoked. Removing it from the identity is a separate call, and is optional.

Integration notes

  • Keep the digest of every claim issued, with the verification record. Revocation takes the digest, and recomputing it needs the exact claim data.

  • For a claim that should end on a known date, set validUntil when issuing. Expiry needs no revocation and no transaction.

  • For a compromised signing key, remove CLAIM_SIGNER from the key. It withdraws every claim that key signed in one transaction.

  • Index ClaimRevoked on the ERC734Validator, filtered by issuer. An application that shows eligibility re-reads isVerified for the identities concerned.

  • A revocation is not reversible. Renewing an attestation is a new claim, with a new issuedAt, issued with 05.

  • Tell the Issuers concerned. The protocol stops counting the claim at once, and the Issuer decides what to do about the positions already held.

Last updated