Skip to content
View RWA-ID's full-sized avatar
πŸ’­
Available
πŸ’­
Available

Block or report RWA-ID

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
RWA-ID/README.md

RWA ID

Human-Readable Identity Infrastructure for Tokenized Real World Assets

Website Whitepaper Technical Docs Status

RWA ID is a non-custodial identity layer that enables RWA platforms to issue human-readable, soulbound or transferable ENS subdomains for clients wallets, tokenized assets, and issuers. Built on proven Web3 standards (ENS + EIP-3668 CCIP-Read), RWA ID provides universal identity resolution across wallets and dApps.

joe.test.rwa-id.eth

🎯 Problem

RWA platforms today face critical identity infrastructure challenges:

  • Opaque wallet addresses create poor user experience
  • Fragmented identities across chains hinder interoperability
  • No shared infrastructure forces every platform to build internally
  • Poor legibility for assets and participants reduces institutional trust

Result: Every platform builds identity systems independently. Nothing interoperates.


✨ Solution

RWA ID provides neutral, shared identity infrastructure that:

  • βœ… Issues human-readable names (e.g., joe.test.rwa-id.eth)
  • βœ… Resolves in all major wallets (MetaMask, Trust, Rainbow, Uniswap)
  • βœ… USDC claim fees with automatic 70/30 platform/protocol split on-chain
  • βœ… Soulbound or transferable β€” configurable per project
  • βœ… Requires no custody or personal data collection
  • βœ… Uses proven standards (ENS + EIP-3668 CCIP-Read)

πŸš€ Status

v3 is live on Ethereum mainnet β€” deployed 1 Aug 2026, block 25661280

  • βœ… Production contracts deployed and verified on Etherscan
  • βœ… Governed by a 2-of-3 Safe multisig (details)
  • βœ… 25 top RWA platform slugs reserved (list)
  • βœ… Identity NFTs render name + artwork fully on-chain (details)
  • βœ… CCIP-Read gateway live at gateway.rwa-id.com, pointed at v3
  • βœ… ENS wildcard resolver active β€” names resolve in MetaMask & Trust Wallet
  • βœ… Platform identity management dashboard operational

What changed in v3

v2 never implemented tokenURI(), so every identity appeared on marketplaces as an untitled, imageless "RWA ID #n". That could not be patched β€” v2 has no baseURI setter and is not behind a proxy β€” so v3 was deployed to replace it.

v2 v3
Token metadata none β€” tokenURI() returned "" name, description, artwork and traits, rendered on-chain
claim() takes bytes32 nameHash string label β€” so the contract can name what it mints
Label casing any bytes accepted lowercase [a-z0-9-_] enforced
Collection metadata none contractURI(), plus ERC-4906 update signalling

Existing allowlists carry over. The Merkle leaf is unchanged β€” keccak256(claimer, keccak256(bytes(label))) β€” so roots and proof sets generated for v2 verify against v3 without regenerating anything.


πŸ“‹ How It Works

For Platforms (3-Step Integration)

  1. Create Project Namespace

    • Platform connects wallet at rwa-id.com
    • Registers namespace (e.g., test.rwa-id.eth) β€” free to create
    • Optionally sets a USDC claim fee (70% goes to platform treasury 30% to RWA ID)
  2. Upload Allowlist

    • Submit CSV mapping names to wallet addresses (two columns: name,wallet)
    • Names must be lowercase [a-z0-9-_] β€” see Label rules
    • System computes the Merkle root in the browser, commits it on-chain, and pins the proofs to IPFS via Pinata. Only the root goes on-chain, so client lists never touch a server the platform does not control
    • A shareable claim URL is generated automatically: rwa-id.com/?claim=[projectId]&proofs=[cid]
  3. Clients Claim Identities

    • Platform shares the claim URL with clients (email, dashboard, etc.)
    • Client opens the URL β€” their wallet is auto-detected from the proof file, no manual input needed
    • Client approves USDC and confirms the claim in two wallet steps
    • Identity NFT minted β€” resolves immediately across all ENS wallets, and displays as client.yourplatform.rwa-id.eth on marketplaces
    • Format: client.yourplatform.rwa-id.eth

Label rules

Labels are restricted to lowercase [a-z0-9-_], 1–63 characters, and the contract rejects anything else at claim time rather than silently normalising it.

This is not cosmetic. The CCIP-Read gateway lowercases a name before hashing it, so under v2 a client allowlisted as Zac minted at keccak("Zac") while ENS looked up keccak("zac") β€” the claim succeeded, nothing errored, and the identity was permanently unresolvable. The contract cannot fold the case itself, because the Merkle leaf is built from the raw bytes off-chain and rewriting them would invalidate every proof. So it rejects instead, and the dashboard normalises when building the tree. The same character set is what keeps on-chain rendering safe, since tokenURI() interpolates the label into both JSON and SVG.

Revenue Sharing Model

Every claim pays a USDC fee β€” always split 70/30 on-chain between the platform treasury and RWA ID. The fee amount depends on whether the platform set one:

Scenario Effective Fee Platform (70%) RWA ID (30%)
Platform sets no fee $0.50 minimum enforced by contract $0.35 $0.15
Platform sets $1.00 $1.00 $0.70 $0.30
Platform sets $5.00 $5.00 $3.50 $1.50

The $0.50 minimum is enforced at the contract level β€” it cannot be bypassed. If a platform sets claimFee = 0, the contract automatically applies the minimum and distributes it with the same 70/30 split.


πŸ“‘ Deployed Contracts

Ethereum Mainnet

Contract Address
RWAIDv3 0x6413e9E6A0D4e05557463A66C34E18192324A2C7 current registry
Wildcard Resolver v2 0x765FB675AC33a85ccb455d4cb0b5Fb1f2D345eb1 unchanged by the v3 cutover
Protocol Safe 0xa28743bD38C9c951910d8FA9812c48ab5CDf75Ab owner + protocol treasury
USDC 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
RWAIDv2 0xD0B565C7134bDB16Fc3b8A9Cb5fdA003C37930c2 superseded β€” no token metadata

The resolver did not need redeploying for the v3 cutover: it stores no registry address, and resolveWithProof only checks that the gateway's response was signed by trustedSigner. Repointing the protocol at a new registry is a gateway configuration change.

Sepolia Testnet

Contract Address
RWAIDv2 0xb0b023c9eD18dCD573B8befC851974f20126ab92
Wildcard Resolver v2 0xE591Cbe3802e3E4908731E3D4B056cd8b08AE520
MockUSDC 0x4CcF36b273dA06D70B235d605639b3f8a6CA6B03

CCIP-Read Gateway

Gateway URL: https://gateway.rwa-id.com/{sender}/{data}.json

The resolver implements EIP-3668 (CCIP-Read) to enable off-chain resolution lookups with on-chain signature verification.

The gateway reads the registry and signs each answer with the trusted signer key registered on the resolver (0xC9fACcf3a77b553375017efFEe441D9770fAA723). Rotating that key requires a Safe transaction calling setTrustedSigner β€” until that lands, rotating it alone would break resolution for every name.


πŸ” Governance

Both the registry and the protocol treasury are controlled by a 2-of-3 Safe multisig (Safe v1.4.1) at 0xa28743bD38C9c951910d8FA9812c48ab5CDf75Ab.

Threshold 2 of 3 signers
Owns RWAIDv3 (owner) and the protocol fee treasury
Cannot touch platform treasuries, seize identities, or move client funds

What requires the multisig

Function Effect
reserveNamespace / batchReserveNamespaces Reserve a slug for a platform
releaseNamespace Release a reservation early
setMinimumClaimFee Change the protocol-wide fee floor (currently $0.50)
setProtocolFeePercent Change the protocol split (currently 30%, bounded 10–50% by the contract)
setProtocolTreasury Redirect the protocol's share of fees
setBaseURI / setContractURI Repoint artwork away from the on-chain renderer

Everything a platform does β€” creating a project, publishing an allowlist, setting its own claim fee and treasury, pausing, revoking β€” is controlled by that platform's own wallet and needs no protocol involvement.

Proposing a multisig transaction

# Dry run β€” prints the slugs, calldata and Safe tx hash, signs nothing
npx hardhat run scripts/reserve-slugs-v3.js --network mainnet

# Sign and queue it for the other owners to approve
SUBMIT=1 npx hardhat run scripts/reserve-slugs-v3.js --network mainnet

Owners then approve and execute at app.safe.global.

Note: the Safe UI may show freshly-verified contract calls as raw hex rather than a decoded function name. Before approving, confirm the target is the registry, value is 0, and the operation is CALL β€” never DELEGATECALL.


🏷️ Reserved Namespaces

25 RWA platform slugs are reserved on v3 until 1 August 2027. Reservations are held at 0x0000000000000000000000000000000000000001 β€” an address nobody controls β€” so the namespace is locked against squatters until the real platform claims it.

Category Reserved slugs
Institutional / securities securitize ondo superstate backed archax
Credit / lending centrifuge maple goldfinch credix clearpool
Real estate realt lofty propy homebase tangible
Infrastructure / compliance polymesh tokeny realio defactor fasset
Commodities / funds openeden swarm bitbond finblox parcl

If one of these is yours: get in touch and the Safe will reassign the reservation to your wallet with reserveNamespace(slug, yourWallet, duration). You can then create the project yourself β€” no other party can take the name in the meantime.

Any other slug is open and can be registered permissionlessly at rwa-id.com. Reservations are not permanent: createProject deletes an expired reservation and lets the next caller through, so anything not claimed by August 2027 becomes available.


πŸ–ΌοΈ Token Metadata

Every v3 identity renders its own metadata on-chain β€” no metadata server, no IPFS dependency, nothing to keep alive:

name        alice.acme.rwa-id.eth
image       on-chain SVG β€” the RWAΒ·ID mark over the full name
attributes  Namespace Β· Label Β· Project ID Β· Transferability Β· Claimed (date)

contractURI() supplies collection-level metadata to marketplaces the same way. setBaseURI and setContractURI exist as escape hatches if artwork should later point elsewhere; setting a baseURI takes precedence over the on-chain renderer, and emits ERC-4906 so marketplaces re-read.


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Wallet    β”‚
β”‚  (User)     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚ Resolve: joe.test.rwa-id.eth
       ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ENS Registry    β”‚
β”‚  (Ethereum)      β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚ Wildcard Resolver β†’ 0x765F...
       ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CCIP-Read        β”‚
β”‚ Gateway          β”‚
β”‚ gateway.rwa-id.comβ”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚ resolveAddr(node) on RWAIDv3
       β”‚   β†’ ownerOf(nodeToTokenId[node]), so a transfer
       β”‚     is reflected without re-registering anything
       β”‚ Returns signed (node, address, hash, sig)
       ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ resolveWithProof β”‚
β”‚ verifies sig     β”‚
β”‚ returns address  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Developer Setup

git clone https://github.com/RWA-ID/RWA-ID.git
cd RWA-ID
npm install
cp .env.example .env   # fill in your keys

Run Tests

npx hardhat test test/RWAIDv2.test.js     # 68 passing

The v2 suite covers the registry logic v3 inherits unchanged β€” projects, allowlists, fee splitting, soulbound enforcement, revocation, CCIP-Read. v3's own additions (on-chain tokenURI, label validation, the label-carrying claim) have no unit suite yet and are exercised by a verification script instead:

npx hardhat run scripts/v3-metadata-check.js

It deploys v3 locally, publishes a real v2-era Merkle root unchanged, claims against it with the original proofs, decodes the resulting tokenURI, and asserts that malformed labels β€” dots, uppercase, spaces, JSON and SVG injection β€” are rejected. Writing proper unit tests for v3 is outstanding work.

npx hardhat test with no arguments also picks up test/rwaIdRegistry.test.js, a legacy v1 suite that fails on a constructor signature change. That predates v3 and does not affect the deployed contracts.

Deploy

npx hardhat run scripts/deploy-v3.js --network mainnet    # dry-runs locally without --network

Prints the deployed address, the block to use as the log-scan start, and the follow-up steps (gateway env var, dashboard constant, Etherscan verification).

Guard the dashboard ABI

npx hardhat compile && node scripts/check-dashboard-abi.mjs

The console declares its own ABI rather than importing artifacts, so a signature change can pass a build and only fail in a user's wallet. This diffs the two.


πŸ“¦ Repository Structure

contracts/
  RWAIDv3.sol                    β€” Current registry (adds on-chain token metadata)
  RWAIDv2.sol                    β€” Superseded registry (no tokenURI)
  RwaIdWildcardResolverV2.sol    β€” ENSIP-10 wildcard resolver (CCIP-Read / EIP-3668)
  mocks/MockUSDC.sol             β€” Test USDC (Sepolia only)
  RwaIdRegistry.sol              β€” v1 contract (legacy)
  RwaIdWildcardResolver.sol      β€” v1 resolver (legacy)
scripts/
  deploy-v3.js                   β€” Deploy RWAIDv3
  deploy-mainnet.js              β€” Deploy v2 (historical)
  deploy-sepolia.js              β€” Deploy to Sepolia testnet
  reserve-slugs-v3.js            β€” Queue v3 slug reservations in the Safe
  reserve-slugs.js               β€” v2 equivalent (historical)
  verify-reservations.js         β€” Verify reserved slugs on-chain
  set-trusted-signer.js          β€” Update gateway signer via Safe multisig
  v3-metadata-check.js           β€” Verify v3 metadata + v2 allowlist compatibility
  check-dashboard-abi.mjs        β€” Diff the console's ABI against the compiled contract
test/
  RWAIDv2.test.js                β€” 68 contract tests
apps/
  rwa-id-dashboard/              β€” Platform console (own repo: RWA-ID/RWA-ID-Dashboard)
packages/
  rwaid-gateway/                 β€” CCIP-Read gateway (deployed on Replit; not tracked here)

πŸ”’ Regulatory Posture

RWA ID operates as infrastructure only with minimal regulatory surface area:

What RWA ID Does What RWA ID Does NOT Do
βœ… Provide identity references ❌ Collect personal data
βœ… Enable human-readable names ❌ Perform KYC/verification
βœ… Facilitate on-chain resolution ❌ Assert identity claims
βœ… Support platform operations ❌ Custody funds or assets

πŸ“ž Contact

Founder: Hector Morel Email: partner@rwa-id.com Website: rwa-id.com


πŸ“„ License

MIT


πŸ™ Built With


RWA ID β€” Identity Infrastructure for the Tokenized Economy

Website β€’ Whitepaper β€’ Technical Docs β€’ Contact

Pinned Loading

  1. RWA-ID RWA-ID Public

    Identity Infrastructure For RWA Platforms And Client Wallets Without Touching KYC Or Internal ID Systems | Human-Readable | Verifiable Across Chains | Built With ENS Β· Ethereum Β· CCIP

    Solidity

  2. x402-Identity x402-Identity Public

    Mint permanent ENS sub domains for AI agents under 402bot.eth | 402api.eth | 402mcp.eth No renewal, Parent Cannot Control giving minters true ownership.

    TypeScript

  3. BuildSite BuildSite Public

    ENS Site Builder

    TypeScript

  4. DMpay-IPFS DMpay-IPFS Public

    Pay To DM On Ethereum

    TypeScript

  5. pet-id pet-id Public

    Pet ID Personalized Page For Cats And Dogs

    TypeScript

  6. robotid-api robotid-api Public

    Robot Identity API For OEM's

    Solidity