> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/guides/claim-issuer/19.-revoke-a-claim.md).

# 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](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md)); 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

```mermaid
sequenceDiagram
    participant Platform
    participant CI as Claim Issuer
    participant CIID as Claim Issuer ONCHAINID
    participant Identity as Investor ONCHAINID
    participant Registry as TREXRegistry

    Platform->>Identity: getClaim(claimId) (read)
    Platform->>CIID: getClaimHash(identity, topic, data), isDigestRevoked(digest) (read)
    Platform->>CI: digest ready, submit
    CI->>CIID: revokeClaimByDigest(digest)
    CIID->>CIID: caller holds MANAGEMENT, digest not already revoked
    CIID-->>Platform: ClaimRevoked(digest, issuer, caller)
    Platform->>CIID: isClaimValid(identity, topic, signature, data) (read)
    Platform->>Registry: isVerified(address) (read)
```

## 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](/guides/identity/22.-add-and-remove-keys-on-an-onchainid.md)). 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](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md).
* Tell the Issuers concerned. The protocol stops counting the claim at once, and the Issuer decides what to do about the positions already held.

## Related flows

* [05 Issue a claim to an investor](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md) : issuing, and re-issuing after a revocation
* [22 Add and remove keys on an ONCHAINID](/guides/identity/22.-add-and-remove-keys-on-an-onchainid.md) : rotating a signing key
* [20 Remove a trusted Claim Issuer](/guides/issuer/20.-remove-a-trusted-claim-issuer.md) : what an Issuer does on its side
* [13 Freeze and unfreeze an address or a partial balance](/guides/agents/13.-freeze-and-unfreeze-an-address-or-a-partial-balance.md) : what an Issuer can do about a holder that became ineligible


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/guides/claim-issuer/19.-revoke-a-claim.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
