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

Coming from ERC-3643 v4

This page is for teams that run or integrate T-REX 4.x and ONCHAINID 2.x. It lists what stays the same in T-REX 5 and ONCHAINID 3, what changes, and what to check for each kind of integration. It is a map: each topic is covered in depth under Concepts and Reference.

What stays the same

  • The ERC-3643 interfaces. IERC3643, IERC3643IdentityRegistry, IERC3643IdentityRegistryStorage, IERC3643TrustedIssuersRegistry, IERC3643ClaimTopicsRegistry and IERC3643Compliance keep their function names. An integration that holds an IERC3643IdentityRegistry reference keeps working against the new registry address.

  • The ERC-20 surface. transfer, approve, transferFrom, balanceOf, totalSupply and the Transfer event behave as ERC-20 tooling expects.

  • The two gates. A transfer still requires isVerified(to) from the registry and canTransfer(from, to, amount) from the compliance, evaluated before the balance moves.

  • The agent operations. mint, burn, forcedTransfer, setAddressFrozen, freezePartialTokens, unfreezePartialTokens, recoveryAddress, pause, unpause and their batch variants keep their names and arguments.

  • The claim model. Claims are signed by Claim Issuers and stored on the holder's identity. A claim is identified by keccak256(abi.encode(issuer, topic)), so an identity holds one claim per issuer and topic. Key purposes 1 to 4 keep their meaning.

  • The utilities. addAndSetModule, the eligibility switch (disableEligibilityChecks, enableEligibilityChecks) and the UtilityChecker are still there.

What changes

Area
T-REX 4.x, ONCHAINID 2.x
T-REX 5, ONCHAINID 3

Scope

A compliant token on one chain.

A register: one reference chain holds the golden copy, satellites run T-REX Lite, connected through ERC-7786.

Identity contract

A monolithic ERC-734 and ERC-735 contract. A passive container of keys and claims.

An ERC-7579 modular smart account. Keys at account level, claims as a module. It holds tokens directly and transacts through ERC-4337.

Signers

ECDSA keys.

Any ERC-7913 signer: ECDSA accounts, smart-contract wallets, passkeys and WebAuthn, RSA.

Key purposes

MANAGEMENT, ACTION, CLAIM, ENCRYPTION.

The same four, with CLAIM named CLAIM_SIGNER, plus CLAIM_ADDER and PROPOSER.

Identity recovery

None at identity level.

Social recovery through the RecoveryModule: weighted guardians, delay, cancellation.

Claim Issuer

A dedicated ClaimIssuer contract.

A regular ONCHAINID of type CLAIM_ISSUER. An EASClaimIssuer adapter resolves EAS attestations as claims.

Claim lifecycle

Valid or revoked. Revocation by signature.

Validity window (issuedAt, validUntil), revocation by digest, and an explicit status: Valid, BadSignature, NotIssued, Revoked, NotYetValid, Expired.

Identity factory

IdFactory, with a Gateway for public deployment.

IdentityFactory: typed identities, a policy and a module set per type, access through an AccessManager.

Where tokens are held

In wallets registered for the token, separate from the identity.

In the identity itself, in wallets linked to it, or both. An identity resolves to itself, so it needs no link to hold a position.

Wallet to identity link

Per token. A Registry Agent registers each wallet with registerIdentity.

Global and self-service. The Identity Owner links a wallet once with IdentityFactory.linkAccount, keyed by ERC-7930 interoperable address, and every token recognizes it. Agent registration still exists as a local binding that takes precedence.

Registries

Four contracts: Identity Registry, Identity Registry Storage, Trusted Issuers Registry, Claim Topics Registry.

Two: TREXRegistry merges the identity, trusted issuers and claim topics registries at one address. IdentityRegistryStorage stays separate and shareable.

Required claim topics

One set per token.

A default set, plus an optional override per identity type.

Investor country

Stored in the Identity Registry Storage.

Not stored by the registry. Country is a compliance concern, owned by a compliance module.

Access control

An owner and a list of agents per contract, with optional agent restrictions.

Roles in an OpenZeppelin AccessManager, granular per operation and scoped per domain.

Compliance modules

moduleCheck returns a boolean. Three action hooks. Each module tracks its own balances.

Typed modules: RULE, SPENDER, TRACKER. A rule answers allowedAmount. The compliance keeps each identity's position and modules read it.

Spender

Not checked. A default-allowance list of trusted contracts.

Checked on transferFrom by SPENDER modules. The identity moves tokens from its linked wallets with identityTransfer.

Balances

Free and frozen.

Free, frozen and bridged, with an in-transit bucket for movements between satellites.

Upgradeability

Custom proxies pointing at a TREXImplementationAuthority, with an IAFactory.

Standard OpenZeppelin beacon proxies. The TREXImplementationAuthority owns the beacons. Isolated suites opt out at deployment.

Deployment

CREATE2 through the TREXFactory, optionally behind the TREXGateway.

CREATE3 through the TREXFactory. Same address on every EVM chain, for the Token and for T-REX Lite.

Storage layout

Sequential slots.

ERC-7201 namespaced storage.

Tooling

Hardhat.

Foundry, with invariant, fuzz and mutation testing and Certora specifications.

Packages

@tokenysolutions/t-rex, @onchain-id/solidity

@t-rex-network/t-rex, @t-rex-network/onchainid

What to check, by kind of integration

Wallets, custodians, venues and indexers

  • totalSupply counts the whole issuance. It includes positions that are active on satellites. A delegation-out or a recall emits a Transfer to or from the zero address on the reference chain, so balanceOf stays correct for every ERC-20 indexer, but an indexer that derives supply by summing Transfer events under-reports by totalBridged(). Reconcile on the DelegatedOut, Recalled and SettledToNative events. The supply that sits on the reference chain is totalSupply() - totalBridged().

  • transferFrom can be refused for the spender. When the Issuer has bound a SPENDER module, a caller that the module does not accept gets SpenderNotAllowed, and the allowance is left untouched.

  • The default allowance is gone. A trusted contract no longer receives an implicit allowance. Holders approve it, or it is listed by a SPENDER module.

  • investorCountry returns zero and updateCountry reverts. Read the country from the compliance module that owns it.

  • owner() returns the AccessManager. It is the suite's authority, not a person. Do not treat it as the Issuer's address.

  • A holder address can be an identity. Do not assume that a token holder is a wallet linked to an identity. An ONCHAINID holds tokens itself, and the registry resolves it to itself.

  • A revoked wallet is not verified. isVerified returns false for a wallet whose link the Identity Owner has revoked. The wallet still resolves to its identity through identity and contains, so its holdings stay attributed and an agent can still recover or burn them.

  • New events to index. ForcedTransfer(agent) follows the Transfer of every forced transfer. IdentityTransfer follows a transfer ordered by the identity. InvestorIdentityChanged names the wallet when its identity is modified. ModuleInteraction now carries the full calldata sent to a module.

Issuers and agents

  • Agents are roles, not a list. There is no addAgent. Grant AGENT_MINTER, AGENT_BURNER and the other roles through the suite's AccessManager. See Actors and roles.

  • The compliance follows its token from the first mint. Once a token has supply, setCompliance, setIdentityRegistry and the compliance's bindToken revert with TokenCirculating. A circulating token's compliance is upgraded in place or changed through its modules. It is never replaced.

  • The registry is its own topics and issuers registry. setClaimTopicsRegistry and setTrustedIssuersRegistry revert with Deprecated.

  • Forced transfers and recovery respect the pause. forcedTransfer and recoveryAddress revert while the token is paused. Mints and burns stay allowed.

  • Recovery notifies the compliance. A recovery is visible to bound modules as a transfer between two wallets of the same identity.

  • Upgrades are versioned and move forward only. The authority publishes a version, then upgrades to it. A rollback onto an older implementation is not possible. Recovery from a bad version is a new version.

  • The factory no longer sets agents. TokenDetails names an AccessManager, or an admin for the one the factory deploys. When the Issuer supplies its own manager, the factory writes nothing into it and the Issuer commissions the suite itself.

Compliance module authors

The module interface is new. A v4 module does not bind to a v5 compliance.

v4
v5

moduleCheck(from, to, value, compliance) returns a boolean

allowedAmount(ctx) returns the largest amount the rule allows

moduleTransferAction, moduleMintAction, moduleBurnAction

One afterTransfer(ctx), for TRACKER modules

Not available

moduleCheckSpender(ctx), for SPENDER modules

Not available

moduleTypes() declares which of RULE, SPENDER, TRACKER the module is

The module resolves identities and tracks balances itself

The module receives a TransferContext with both identities resolved, and reads positions from the compliance ledger

The modules that ship with T-REX 5 are MaxBalancePerIdentityModule, SpenderVerificationModule and SpenderWhitelistModule. The v4 modules do not run on v5: the module interface changed in depth, so each rule is implemented anew for it, and the rules of the v4 catalogue are expected on the new interface. The guide is under Build: Write a compliance module. How the token layer relates to the standard is in T-REX and ERC-3643.

Claim Issuers and identity integrators

  • ONCHAINID 3 is a new deployment. It is not storage-compatible or interface-compatible with 2.x. Identities are created again through the IdentityFactory.

  • The claim payload is a structure. addClaim and isClaimValid take a ClaimData (issuedAt, validUntil, metadataHash, payload) where 2.x took raw bytes. The metadataHash binds the scheme and the URI to the signature.

  • Claims are signed as ERC-712 typed data, in the domain of the issuer's identity. A signature cannot be replayed against another identity.

  • Revocation is by digest. revokeClaimByDigest replaces revokeClaimBySignature. Removing a claim from the holder's identity also marks its digest as spent.

  • A Claim Issuer is an identity of type CLAIM_ISSUER, created through the factory by an authorized party. With sufficient standing in the ReputationRegistry, it adds its claims to an identity directly, through addClaimTo.

  • Key hashes changed. A key is identified by keccak256 of its signer bytes. For an address, that is the hash of the 20 address bytes, not of the 32-byte ABI encoding used in 2.x.

  • execute and approve live in a module. The ERC-734 execution queue is the KeyApprovalModule. These entry points, and addClaim and removeClaim, require a direct call from the key holder. They are not reachable through a user operation or a relayed call. User operations go through the account's ERC-7579 execution path, which serves calls to external contracts and management operations, not claim writes.

  • Wallet links are permanent records. A link is made with a signature from the wallet. Revoking it is terminal: the wallet keeps its record and can never be linked again, to any identity.

Removed in v5

  • The DvATransferManager and DVDTransferManager contracts.

  • The TREXGateway.

  • The AgentManager and OwnerManager role contracts, addAgent, removeAgent and setAgentRestrictions.

  • The default-allowance mechanism.

  • The custom proxy stack: AbstractProxy, the per-contract proxies, IAFactory, setImplementationAuthority on proxies.

  • The ONCHAINID Gateway, Verifier, ImplementationAuthority and IdentityProxy contracts, and the standalone ClaimIssuer implementation. The IClaimIssuer interface remains.

Migrating

ONCHAINID 3 is a new deployment, not an upgrade of 2.x proxies. The 2.x implementation remains available in its original repository.

T-REX 5 is a new deployment too. There is no upgrade path from a T-REX 4.x token suite to T-REX 5: a 4.x proxy cannot be pointed at a 5.0 implementation.

What changed
Why it rules out an in-place upgrade

Storage layout

Every contract keeps its state in ERC-7201 namespaces. The slots of a 4.x contract are not where a 5.0 implementation reads.

Base contracts

The suite is built on OpenZeppelin Contracts 5, whose own storage differs from the versions 4.x was built on.

Structure of the suite

The registries are merged, the roles moved to an access manager, and the compliance keeps positions from the token's first mint.

An asset that moves from 4.x to 5 is redeployed as a new suite, and its holders' positions are issued again on it under the Issuer's own procedure. Investors use ONCHAINID 3 identities.

Audits

ONCHAINID 3 was audited by OpenZeppelin. The report is public: ONCHAINID Audit. The audit of T-REX 5 is in progress. See Audits and verification.

Last updated