Skip to main contentA-REX Foundation

निर्णय रिकॉर्ड · ADR-021

ADR-021: ONCHAINID claims whose validity is A-REX trust, computed live

ERC 3643 decides who may hold a token with ONCHAINID: each holder's wallet points to an identity contract (ERC 734 keys, ERC 735 claims), and the token's identity registry requires claims of given topics signed by claim

**Proposed** (2026-10-23). Reference adapter available; informative, adds no requirement to AREX-CORE.md
दस्तावेज़ आईडी
ADR-021
निर्णय की तिथि
2026-10-23
स्रोत
docs/adr/ADR-021.md
केवल अंग्रेज़ी में उपलब्ध
यह पृष्ठ अंग्रेज़ी में है। श्वेतपत्र के अध्याय और आरेख अनूदित हैं। नॉर्मेटिव मानक रिपॉज़िटरी में रहता है; उस पाठ के लिए शीघ्र पहुँच का अनुरोध उपयोग करें। सिस्टम डिज़ाइन मार्गदर्शिकाएँ और निर्णय रिकॉर्ड अंग्रेज़ी में रहते हैं।

A company's identity claim (KYB) signed by an issuer that A-REX trusts becomes an ONCHAINID claim through a claim issuer contract that answers isClaimValid from the A-REX trust list at the moment it is asked, so ERC-3643 identity registries accept it while, and only while, A-REX trusts its signer.

FieldValue
IDADR-021
Subject areaInteroperability, identity
StatusProposed (2026-10-23). Reference adapter available; informative, adds no requirement to AREX-CORE.md
Date2026-10-23
OwnersA-REX Contributors; requested by the A-REX Platform (owner decision D5)
Related requirementsAREX-CORE §6 (attestations, trusted issuers per topic), ADR-008, ADR-019
Supersedes / superseded by—

Context

ERC-3643 decides who may hold a token with ONCHAINID: each holder's wallet points to an identity contract (ERC-734 keys, ERC-735 claims), and the token's identity registry requires claims of given topics signed by claim issuers it trusts. T-REX's IdentityRegistry.isVerified reads the claim from the identity and asks the claim's issuer contract isClaimValid(identity, topic, signature, data); ONCHAINID's Identity.addClaim asks the same question before it stores a claim. Neither looks at anything else.

A-REX has its own trust model: trusted issuers per topic (IARexAttest.isTrustedIssuer(topic, issuer)), set by the token's administrator, with revocation semantics fixed by ADR-019 (only the issuer, or a revoker it delegated, revokes). Companies onboarded on A-REX are checked (KYB) by issuers A-REX trusts. Without a bridge, a company that wants to hold or trade ERC-3643 tokens must be checked again by an ONCHAINID claim issuer, and a withdrawal of trust on one side is not seen on the other.

Issue

How can a company's A-REX identity standing be presented as ONCHAINID claims that ERC-3643 registries accept, without a second source of truth that can drift from A-REX trust?

Assumptions

  • ERC-3643 registries and ONCHAINID identities validate claims only through isClaimValid on the issuer (T-REX 4.1.6, ONCHAINID 2.2.1, verified in their source).
  • KYB claims are about companies. The claim data needs no personal data: a hash of the evidence, the ISO 3166-1 numeric country of registration, an expiry.

Constraints

  • No personal data on-chain (ADR-008); a claim stored in an identity is public.
  • Revocation is the issuer's (ADR-019).
  • ONCHAINID claim format: signature over keccak256(abi.encode(identity, topic, data)) with the Ethereum signed-message prefix, scheme 1 (ECDSA), claim id keccak256(abi.encode(issuer, topic)).

Alternatives considered

AlternativeForAgainstOutcome
Use an ONCHAINID ClaimIssuer whose CLAIM keys copy the A-REX trusted issuersstock ONCHAINIDa second list to keep in sync; a distrusted issuer stays valid until someone removes its keyRejected
Copy claims into identities and revoke them when A-REX trust changes (push)works with any issueran off-chain process stands between a distrust and its effect; missed events leave valid claimsRejected
A claim issuer contract whose isClaimValid asks the A-REX trust source on every callone source of truth; distrust takes effect in the same block everywhereone extra external call per verification; the trust source must stay availableProposed

Decision (proposed)

ARexClaimIssuer (arex-contracts contracts/reference/interop/) implements the claim-issuer part of ONCHAINID's IClaimIssuer:

  • isClaimValid(identity, topic, sig, data) is true only if all of these hold at that moment:
    1. topic is mapped to an A-REX topic (setClaimTopic(claimTopic, arexTopic); the natural mapping is claimTopic = uint256(arexTopic), for example uint256(keccak256("AREX:KYB")));
    2. data is abi.encode(bytes32 evidenceRef, uint16 country, uint64 expiresAt) and has not expired;
    3. the signature is ONCHAINID's format, recovered without malleable signatures, or, since the amendment of 2026-10-27, the signature of a contract account (ERC-1271) as described below;
    4. the signature has not been revoked here;
    5. the trust source (IARexAttest.isTrustedIssuer(arexTopic, signer)) trusts the signer.
  • It never reverts for a bad claim: it answers false.
  • revokeClaim(claimId, identity) reads the claim from the identity and revokes it if the caller is its signer or a revoker the signer named (setRevoker). revoke(identity, topic, sig, data) does the same for a claim not stored in an identity. revokeClaimBySignature reverts: a signature alone does not prove who signed it.
  • A wallet links itself to an identity on which it holds a MANAGEMENT key (linkIdentity); identityOf(wallet) and countryOf(wallet) answer the ERC-3643 adapter's identity and investorCountry (ADR-020).
  • The trust source is fixed at deployment. Which A-REX topics are bridged, which claim topics they become and which trust source is used are policy (ADR-019): an implementation's profile, the company and the registry owner who decides to trust the bridge.

A registry owner trusts the bridge as a claim issuer for a topic (T-REX TrustedIssuersRegistry.addTrustedIssuer). By doing so it trusts whoever administers the bridge's trust source to choose KYB issuers, and it can read that source (trustSource()) before deciding.

Argument

Both consumers ask exactly one question of a claim issuer, so answering it from A-REX state makes the A-REX trust list the only list. A distrust in A-REX invalidates every claim its issuer signed in every registry in the same block, with no process to run and nothing to forget. Keeping the claim format identical to ONCHAINID's means the company's claims are signed with the same tools, stored in an ordinary ONCHAINID identity, and verifiable off-chain by anyone who checks the signature and asks the bridge.

Consequences

Positive

  • A company checked once on A-REX can be verified by any ERC-3643 registry that trusts the bridge.
  • Distrust, expiry and revocation take effect immediately and everywhere.
  • No personal data: the claim is a hash, a country and a date.

Negative

  • Every verification costs an external call to the trust source (about 3,000 to 16,000 gas per isClaimValid).
  • A registry owner must trust the bridge's trust source; the bridge cannot make a weak trust source strong.
  • Claims are public in the company's identity, as all ONCHAINID claims are.

Obligations it creates

  • Implementations publish which trust source a bridge reads and who administers it.
  • Issuers revoke with revokeClaim / revoke, not by deleting keys.
  • The conformance clause IC-5 of interop/ERC-3643.md holds (the bridge holds no role in the token).

Implementation and evidence

WhatWhere
Contractarex-contracts contracts/reference/interop/ARexClaimIssuer.sol, interfaces/IOnchainID.sol
Testsarex-contracts test/foundry/ClaimIssuer.t.sol: a real ONCHAINID 2.2.1 Identity accepts the claim; a real T-REX 4.1.6 IdentityRegistry verifies the company with it; distrust, expiry and revocation turn it off; fuzzed signers and malformed data. test/foundry/ClaimIssuerContractSigner.t.sol (from 2.0.0-alpha.7): the same with a contract account as signer, revocation covering every signature of a claim, non-canonical envelopes
Mappinginterop/ERC-3643.md §C
First consumerA-REX Platform add-on "Company identity on ONCHAINID"

Amendment 2026-10-27: signers that are contract accounts (ERC-1271)

Still Proposed. The first consumer's companies and certifiers sign with accounts that are contracts (Safes whose owners are passkeys), which cannot produce an ECDSA signature. Asking them for a separate key, or having the platform hold one for them, would make the platform a signer of other parties' claims. Reference 2.0.0-alpha.7 of ARexClaimIssuer:

  • a claim's sig is either the 65-byte ECDSA signature (scheme 1, unchanged) or the canonical abi.encode(address signer, bytes signature) of a contract account (ERC-735 scheme 3, "contract verification"; contractSignature(signer, signature) builds it). The claim is valid when, in addition to the conditions above, signer.isValidSignature(claimDigest(identity, topic, data), signature) returns the ERC-1271 magic value. Trust is read before the account is called, so only trusted accounts are called. Any other encoding (other offsets, padding or trailing bytes) is not valid, and isClaimValid still never reverts;
  • the digest is the same for both schemes, so a claim signed either way is verified by the same rule;
  • a revocation covers the claim (signer, identity, topic, data), not only the bytes revoked. A contract account can produce other valid signatures of the same claim (a Safe ignores bytes appended to its signatures), so a revocation keyed by the signature alone could be undone by anyone who appends bytes. isClaimRevoked(sig) keeps answering for that exact signature, and isClaimRevokedFor(signer, identity, topic, data) answers for the claim;
  • a contract account revokes as itself (the named signer is msg.sender) or through a revoker it named, as ADR-019 requires;
  • getRecoveredAddress stays ECDSA-only: a contract signature is checked, never recovered.

Instances of earlier releases accept ECDSA only and are not upgradeable. Moving to the new instance means a new claim-issuer address, so claims are signed again for it and wallets link themselves again. The conformance clause OID-3 of interop/ERC-3643.md covers the claim-level revocation.

  • ADR-008: no personal data on-chain
  • ADR-019: capabilities in the standard, policy in profiles; revocation by the issuer
  • ADR-020: ERC-3643 compatibility