05. Issue a claim to an investor
Issuing a claim records, on an investor's identity, that a Claim Issuer vouches for a fact about it: identity verified, accredited, resident of a jurisdiction. The Claim Issuer verifies the investor off-chain, signs the claim, and the claim is added to the investor's ONCHAINID. From then on, every asset that trusts that issuer for that topic counts the claim. This is what makes an investor eligible.
At a glance
Triggered by
Claim Issuer
Actors
Claim Issuer, Investor, Identity Owner, Platform
Contracts
The ONCHAINID of the Investor, the ONCHAINID of the Claim Issuer, ERC734Validator, IdentityFactory and ReputationRegistry (read only, during the check of the issuer)
Preconditions
The Investor has an ONCHAINID (see 02); the Claim Issuer has an ONCHAINID of type CLAIM_ISSUER with a CLAIM_SIGNER key; the Claim Issuer has verified the Investor under its own process; either the Claim Issuer has standing in the network, or the Investor's identity has granted it a claim key, or the Investor adds the claim itself
Result
The Investor's identity holds a valid claim from the Claim Issuer for the topic
Actors and roles
Claim Issuer
Verifies the Investor, signs the claim and, in the usual path, adds it to the Investor's identity.
An ONCHAINID of type CLAIM_ISSUER. A CLAIM_SIGNER key to sign. A MANAGEMENT key to submit
Investor
Is the subject of the claim. Provides its documents off-chain.
An ONCHAINID
Identity Owner
The Investor in its capacity as controller of the identity. Transacts only when it adds the claim itself.
A CLAIM_SIGNER or CLAIM_ADDER key on its identity
Platform
Carries the verification session, builds the claim and relays the calls.
Whatever keys the Claim Issuer or the Investor has authorized
Sequence
Step by step
Step 1. Verify the Investor
Who: Claim Issuer
Call: Off-chain
Before the call: The Investor has given the address of its ONCHAINID and the documents the verification requires. When the Investor comes with a wallet that has no identity yet, the Claim Issuer creates one for that wallet first, with the wallet as its only manager (02).
What happens: The Claim Issuer verifies the Investor under its own process and regulation. It confirms that the person it verified controls the identity it will attest. The result of the verification, and the documents, stay with the Claim Issuer.
What changes: Nothing on-chain.
Step 2. Build and sign the claim
Who: Claim Issuer (CLAIM_SIGNER key)
Call: Off-chain, using read calls
Before the call: Step 1 concluded that the fact can be attested.
What happens: The Claim Issuer builds the claim.
topic
The claim topic agreed with the Issuers that rely on it, for example <KYC topic>. Not zero.
scheme, uri
How the claim is to be read, and where supporting material is.
data.issuedAt
The time of signing. Not zero.
data.validUntil
The time after which the claim expires. Zero for no expiry.
data.metadataHash
getMetadataHash(scheme, uri), read on the ERC734Validator, the module whose address Identity.registryModule() returns. It binds the scheme and the URI to the signature.
data.payload
The content for the topic: a hash or an encoded value, not raw personal data.
It reads getClaimHash(identity, topic, data) on its own ONCHAINID, which returns the ERC-712 digest of the claim in the issuer's signing domain, and signs that digest with a key that holds CLAIM_SIGNER on its identity. The signature field of the claim carries the signer and its signature together.
What changes: Nothing on-chain.
Step 3. Add the claim to the identity
There are two ways. The first is the usual one.
Who: Claim Issuer (MANAGEMENT key of its identity)
Call: addClaimTo(topic, scheme, signature, data, uri, identity), called on the Claim Issuer's ONCHAINID
Before the call: Step 2 is done. The call is made directly on the issuer's identity by the key holder.
What the contract checks:
The caller holds
MANAGEMENTon the Claim Issuer's identity. Otherwise the call reverts withSenderDoesNotHaveManagementKey.The claim is valid for this issuer: inside its validity window, not revoked, signed by a
CLAIM_SIGNERkey of the issuer, with a signature that verifies. OtherwiseInvalidClaim.On the Investor's identity: the Claim Issuer's identity holds a
CLAIM_SIGNERorCLAIM_ADDERkey there. If it does not: its identity is of typeCLAIM_ISSUERin theIdentityFactory, and its reputation is at least the claim-add threshold. OtherwiseIdentityNotClaimIssuerTypeorReputationBelowClaimAddThreshold.The topic is not zero. Otherwise
InvalidClaimTopic.The signature, the payload and the URI are within their size limits. Otherwise
ClaimSignatureTooLong,ClaimPayloadTooLongorClaimUriTooLong.data.metadataHashmatches the scheme and the URI. OtherwiseClaimMetadataMismatch.The issuer confirms the claim:
isClaimValid(identity, topic, signature, data)returns true. OtherwiseInvalidClaim.
What changes: The Investor's identity stores the claim under claimId = keccak256(abi.encode(issuer, topic)). If the identity already held a claim from this issuer for this topic, it is replaced. The ERC734Validator emits ClaimAdded, or ClaimChanged for a replacement, with the identity, the claim and the caller, and ClaimAddedTo for the write made by the issuer.
Alternative: the Investor adds the claim.
Who: Identity Owner (CLAIM_SIGNER or CLAIM_ADDER key of the Investor's identity)
Call: addClaim(topic, scheme, issuer, signature, data, uri), called on the Investor's ONCHAINID
Before the call: The Claim Issuer has sent the signed claim to the Investor.
What the contract checks: The caller holds CLAIM_SIGNER or CLAIM_ADDER on the identity. Otherwise SenderDoesNotHaveClaimSignerKey. Then checks 4 to 7 above.
What changes: The same.
Step 4. Confirm the effect
Who: Platform
Call: Off-chain, using read calls
Before the call: Step 3 is confirmed.
What happens: The Platform reads getClaim(claimId) on the Investor's identity, and isClaimValid(identity, topic, signature, data) on the Claim Issuer's identity, which must return true. For an asset the Investor wants to hold, it reads TREXRegistry.isVerified(address) for one of the Investor's addresses.
What changes: Nothing on-chain.
State after the flow
The Investor's identity holds one claim from this issuer for this topic, readable with
getClaim(claimId)and listed bygetClaimIdsByTopic(topic).The Claim Issuer answers
isClaimValidwith true for that claim, until it expires, is revoked, or its signing key is withdrawn.Every asset that requires the topic and trusts this issuer for it counts the claim, for every address of the identity, on every chain.
No asset was touched. No registry of any asset changed.
No personal data is on-chain.
Failure modes
Reverts with SenderDoesNotHaveManagementKey
addClaimTo was called by a key that does not hold MANAGEMENT on the issuer's identity (step 3, check 1)
Submit with a MANAGEMENT key. The signing key signs, it does not submit
Reverts with InvalidClaim
The claim does not validate: wrong digest, signer without CLAIM_SIGNER, issuedAt zero or in the future, expired, or already revoked (step 3, checks 2 and 7)
Read getClaimStatus on the ERC734Validator, with the issuer's identity as the caller of the read, to see which. Sign a fresh claim
Reverts with IdentityNotClaimIssuerType
The issuer has no claim key on the Investor's identity and is not a CLAIM_ISSUER identity of the factory (step 3, check 3)
Have the Investor add the claim itself, or grant the issuer a claim key
Reverts with ReputationBelowClaimAddThreshold
The issuer's reputation is below the network threshold (step 3, check 3)
Same. Or have the REPUTATION_MANAGER review the issuer
Reverts with ClaimMetadataMismatch
metadataHash was not computed from the scheme and the URI submitted (step 3, check 6)
Compute it with ERC734Validator.getMetadataHash(scheme, uri)
Reverts with InvalidClaimTopic
The topic is zero (step 3, check 4)
Use the agreed topic
Reverts with a size error
The signature, the payload or the URI exceeds 2,048 bytes (step 3, check 5)
Put a hash in the payload, not the data
Reverts with SenderDoesNotHaveClaimSignerKey
In the alternative path, the caller holds neither CLAIM_SIGNER nor CLAIM_ADDER on the Investor's identity
Use a key that does, or a MANAGEMENT key
The call is refused when sent as a user operation
addClaim and addClaimTo require a direct call from the key holder
Call the identity directly
Common misunderstandings
Wrong: "The protocol issues the KYC." Or: "The Issuer issues the claim."
Right: A Claim Issuer signs claims. The protocol stores them and checks them. The Issuer of an asset decides which Claim Issuers it trusts and for which topics. It can run its own Claim Issuer, which is then a separate role with its own identity.
Wrong: "A claim is issued for a token."
Right: A claim is about an identity, not about an asset. One claim serves every asset that trusts its issuer for its topic. An investor verified once is not verified again per asset.
Wrong: "A claim is issued to a wallet."
Right: A claim is added to the ONCHAINID. Every address of the identity shares it: the identity's own address and every linked wallet, on every chain.
Wrong: "The claim contains the investor's data."
Right: The claim contains a topic, the issuer, a validity window, a signature and a payload that is a hash or an encoded value. The documents stay off-chain with the Claim Issuer.
Integration notes
Read
getClaimHash(identity, topic, data)from the issuer's identity to obtain the digest to sign. Do not rebuild the typed data by hand.Set
validUntilto the date after which the verification has to be renewed. Expiry needs no transaction, and the investor stops being eligible at that moment.Re-issuing for the same topic replaces the previous claim from the same issuer. Renewal is this same flow.
Keep the signing key and the submitting key apart. A signing service holds
CLAIM_SIGNER. Submission and revocation takeMANAGEMENT.Store, off-chain, the digest of each claim issued with the verification record. It is what
revokeClaimByDigesttakes.Index
ClaimAdded,ClaimChangedandClaimRemovedon theERC734Validator, filtered by identity or by issuer.An Investor without a gas token receives its claims through the first path. The Claim Issuer pays.
A Claim Issuer with standing needs no approval from the Investor to add a claim. This is by design: asking for an acceptance on every claim would add a step to every onboarding. The gate is upstream, on who can be a Claim Issuer at all. The Investor can remove a claim from its identity afterward.
Related flows
19 Revoke a claim : withdrawing the attestation
02 Deploy an ONCHAINID : the Investor's identity, and the Claim Issuer's
04 Add a trusted Claim Issuer : what makes the claim count for an asset
03 Configure required claim topics : which topics an asset requires
08 Mint a position to an investor : where eligibility is first checked
Last updated