Developer Foundation

RWA System Design

Explore how RWA systems are designed, from vault and custody architecture to compliance, settlement and on-chain asset lifecycle flows.

Last updated: 12/5/2025
Improve this page

This chapter provides a detailed blueprint for building scalable and compliant RWA protocols that bridge traditional financial infrastructure with modern blockchain architecture. For protocol engineers and security auditors, the core message is clear: RWAs are not simply DeFi with real assets attached. They rely on hybrid systems that coordinate legal entities, financial intermediaries, verified data pipelines, and strict on-chain enforcement. When any of these layers fall out of alignment, the result can be regulatory breaches, liquidity stress, or failed audits.
 

We explore the full stack of RWA design, including participant abstractions with role based access, end to end data flows supported by cryptographic proofs, modular compliance frameworks built on attestations, asynchronous settlement mechanics using standards such as ERC 7540, and legally aligned token models. All patterns and examples are drawn from production grade systems in 2025, such as Ondo USDY v2 with Chainlink V2.5 powered async vaults, Mountain Protocol’s USDM with UMA secured reserves, OpenEden TBILL with LayerZero attestation flows, Centrifuge V3’s Merkle verified credit pools, Maple Finance’s ERC 1404 partitioned loans, and Backed’s Schroders managed equity tokens.
 

Expect practical Solidity interfaces, Mermaid sequence diagrams, optimized patterns for L2 environments, including Arbitrum, Optimism, and Base, and targeted audit checklists aimed at both economic and technical security.
 

High-Level System Architecture

RWA systems operate across three tightly connected layers: the off-chain layer that mirrors traditional financial operations, the oracle and messaging layer that transports verified data, and the on-chain layer that executes immutable enforcement rules. These layers function as a coordinated pipeline. Off-chain activities such as NAV calculations or settlement updates produce signed data that flows on chain through secure messaging. At the same time, compliance requirements and access controls move in both directions, ensuring that every participant action aligns with regulatory and operational constraints.

Screenshot 2025-12-02 at 1.06.13 AM.png

Flow Annotations

  • Push Flows: NAV and reserve data move from the off-chain source to the oracle layer and then to the on-chain vault, typically through scheduled updates such as daily Chainlink cron jobs.
     
  • Pull Flows: On-chain contracts request compliance or eligibility checks from the compliance layer before actions like minting or transferring are allowed.
     
  • Async Flows: Settlement events occurring off-chain are confirmed asynchronously, with updates relayed to on-chain contracts after T plus 1 to T plus 30 cycles, depending on asset class.
     
  • Cross Chain Flows: Attestations and verified updates are propagated across networks, enabling multi-chain yield and liquidity operations, as seen in systems like OpenEden that relay TBILL yields from Ethereum to Solana.
     

Off-Chain Participants

Model every off-chain participant as a cryptographic principal with a well-defined on-chain interface. Use OpenZeppelin’s AccessControlEnumerable for role assignments, ECDSA for signature validation, and events for system observability.

ParticipantCore ResponsibilitiesOn-Chain Abstraction (Solidity Interface)2025 Integration Example
SPV / TrustHolds legal ownership of RWAs and issues economic rights through subscription agreements.interface ISPV { function mapRights(address holder, uint256 shares, bytes calldata legalProof) external; } (Vault stores immutable SPV address.)Ondo USDY: A Delaware SPV holds BlackRock BUIDL fund shares; token claims reference IPFS-gated subscription docs.
CustodianSafekeeps assets such as gold, T bills, or securities, and signs reserve attestations.interface ICustodian { function attestReserves(bytes calldata payload, bytes calldata sig) external; } (Uses ECDSA for validation.)Mountain USDM: BNY Mellon signs daily CUSIP hashed reserve proofs via Chainlink with built in liquidity haircut.
Bank AccountsHandles fiat settlements and escrow flows.No direct interface; relies on oracle callbacks: function onSettlementConfirmed(uint256 txHash, uint256 amount) external; triggered by API integrations.OpenEden TBILL: ACH and wire deposits confirmed via API3; system holds a 5 percent buffer for FX and timing mismatches.
KYC / AML ProviderPerforms onboarding, sanctions checks, and issues verifiable credentials.interface IIdentityIssuer { function issueVC(address subject, bytes32 schemaUID, bytes calldata data) external returns (bytes32 vcId); } (DID compatible)Centrifuge V3: Shufti Pro checks produce ERC 7208 identity claims used for tiered investor access.
Auditors / UnderwritersValidate NAV, assess credit quality, and provide independent risk scoring.interface IAuditor { function challengeNAV(uint256 proposedNAV, bytes calldata evidence) external returns (bool accepted); } (UMA style dispute engine)Maple Finance: Credora feeds borrower credit scores; disputes bonded with 5K ETH and resolved within 48 hours.
Asset ManagersManage portfolios and compute NAV using assets minus liabilities over outstanding shares.interface IManager { function previewRebalance(uint256 newNAV) external view returns (uint256 yieldAccrual); } (Integrates with ERC4626 vault hooks.)Backed Finance: Schroders posts weekly NAVs via Redstone to Polygon vaults with a one percent tolerance threshold.

Off-Chain to On-Chain Data Flow

The data bridge between off-chain systems and on-chain contracts must be verifiable, timestamped, and resilient to disputes. Simple numeric updates are insufficient, structured proofs ensure integrity and auditability. Update frequencies should align with asset liquidity: roughly every 24 hours for liquid instruments like T-bills, every 72 hours for semi-liquid products such as corporate bonds, and weekly for illiquid assets, including private credit.

Use EIP 712 typed data for type-safe signatures, oracle networks for secure delivery, and Merkle trees to batch supporting documents or position data into compact, verifiable payloads.

RWA Design.svg

EIP-712 Proof Schema

1// NOTE: Sample code - not for production use.
2
3// SPDX-License-Identifier: MIT
4pragma solidity ^0.8.24;
5
6import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
7import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
8import "@openzeppelin/contracts/access/AccessControl.sol";
9
10struct ReserveProof {
11    uint256 timestamp;          // UTC-aligned block.timestamp
12    address assetAddress;       // ERC-20/3643 proxy for RWA
13    uint256 totalValueUSD;      // 18-decimal USD equivalent (Chainlink price feed)
14    uint256 circulatingShares;  // Matches vault.totalSupply()
15    bytes32 docMerkleRoot;      // IPFS hashes of custody statements/PDFs
16    // Sig embedded for relayer submission
17    uint8 v;
18    bytes32 r;
19    bytes32 s;
20}
21
22bytes32 constant PROOF_TYPEHASH = keccak256(
23    "ReserveProof(uint256 timestamp,address assetAddress,uint256 totalValueUSD,uint256 circulatingShares,bytes32 docMerkleRoot)"
24);
25
26abstract contract Provable is EIP712, AccessControl {
27    using ECDSA for bytes32;
28    bytes32 public constant CUSTODIAN_ROLE = keccak256("CUSTODIAN_ROLE");
29
30    constructor() EIP712("RWAProof", "1") {}
31
32    function _hashTypedDataV4(bytes32 structHash) internal view virtual override returns (bytes32) {
33        return _domainSeparatorV4() ^ keccak256(abi.encode(structHash));
34    }
35
36    function verifyAndUpdateProof(ReserveProof calldata proof, address expectedCustodian) external onlyRole(CUSTODIAN_ROLE) {
37        bytes32 structHash = keccak256(abi.encode(PROOF_TYPEHASH, proof.timestamp, proof.assetAddress, proof.totalValueUSD, proof.circulatingShares, proof.docMerkleRoot));
38        bytes32 digest = _hashTypedDataV4(structHash).toEthSignedMessageHash();
39        require(digest.recover(proof.v, proof.r, proof.s) == expectedCustodian, "Invalid custodian sig");
40        // Store & rebase: e.g., _updateTotalAssets(proof.totalValueUSD);
41        emit ProofVerified(proof.timestamp, proof.totalValueUSD);
42    }
43}
44

Delivery Mechanisms

  • EIP 712 Direct: A relayer submits verifyAndUpdateProof, providing a lightweight and low-latency delivery path (approximately 50k gas on Arbitrum).
     
  • Oracles:
    • Chainlink Automation: Push-based scheduling with predictable costs (around ten cents per transaction).
    • API3 Airnode: Pulls data directly from custodian APIs with high availability and minimal middleware.
    • UMA: Provides an optimistic verification layer backed by economic incentives, using a bonded dispute mechanism for NAV challenges.
       
  • Merkle Proofs: Ideal for batching large sets of documents, such as invoice portfolios or position reports. The Merkle root is stored on-chain, while off-chain clients verify inclusion using Merkle.verify(leaf, proof, root).

Vault Integration

1// NOTE: Sample code - not for production use.
2contract RWACompliantVault is ERC4626, Provable {
3    mapping(uint256 => ReserveProof) public historicalProofs;
4    uint256 public latestProofTimestamp;
5
6    function updateFromProof(ReserveProof calldata proof) external {
7        verifyAndUpdateProof(proof, custodian);  // custodian is role-bound
8        historicalProofs[proof.timestamp] = proof;
9        latestProofTimestamp = proof.timestamp;
10        // Rebase: sharesPrice = proof.totalValueUSD * 1e18 / proof.circulatingShares;
11        _accrue();
12    }
13
14    function convertToAssets(uint256 shares) public view override returns (uint256 assets) {
15        if (latestProofTimestamp == 0) return 0;
16        ReserveProof memory latest = historicalProofs[latestProofTimestamp];
17        assets = (shares * latest.totalValueUSD * 1e18) / latest.circulatingShares;
18    }
19
20    // Yield accrual hook
21    function _accrue() internal virtual {
22        // e.g., totalAssets += (block.timestamp - lastAccrue) * yieldRate;
23    }
24}
25

Identity, Whitelisting and Compliance

Compliance in modern RWA systems is proactive and embedded directly into transfer logic through modular claim checks. The industry is moving away from static, manually maintained whitelists and toward dynamic attestations using standards like ERC 7208, which scale better for regulations such as MiCA and Reg S. A major 2025 shift is the use of zero-knowledge proofs to preserve user privacy in regulated environments, including approaches like Semaphore-based signaling for anonymous yet compliant EU investor pools.

Onboarding Flow

  1. The investor submits identification documents to the KYC provider, who completes screening before the issuer (multisig or DAO) approves the onboarding.
  2. A verifiable credential or decentralized identifier is minted and synced to the on-chain compliance registry through an oracle feed.
  3. Token transfer hooks query the compliance registry before every movement, ensuring that only eligible and verified participants can transact.
     

Enforcement in Tokens (ERC-3643 Hooks)

  • Pre-Transfer Checks

    1function _beforeTokenTransfer(address from, address to, uint256 amount)
    2    internal
    3    override
    4{
    5    require(
    6        registry.isEligible(to, allowedJurisdiction),
    7        "Non-compliant transfer"
    8    );
    9}
    10
    11

    Enforces eligibility and jurisdiction constraints before any token movement.

  • Geo-Blacklist Controls Oracle maintained jurisdiction flags (for example, Chainalysis through API3):

    1mapping(uint8 => bool) public restrictedJurisdictions;
    2
    3
  • Lockup Enforcement

    1mapping(address => uint256) public vestingUnlock;
    2if (block.timestamp < vestingUnlock[to]) revert();
    3
    4

    Ensures time based transfer restrictions.

  • Account Freezes

    1function forceFreeze(address account, uint256 amount)
    2    external
    3    onlyRegulator
    4{}
    5
    6

Often paired with ERC 1404 partitions for class-based asset freezes. Systems such as OpenEden now use multi-schema Verax credentials that combine KYC, tax residency, and accreditation in a single verification layer.
 

Settlement and Accounting

RWA systems operate on real-world settlement timelines, where instant finality is not possible for wires, custody movements, or deed transfers. Standards like ERC 7540 help decouple on-chain mint and burn events from off-chain fulfillment, reducing the risk of liquidity illusions or over-issuance. Most production systems maintain operational buffers of 5 to 15 percent of TVL to handle timing mismatches and unexpected settlement delays.
 

Timelines and State Tracking

  • Deposits: T plus 0 provisional mint, followed by T plus 1 to T plus 3 settlement once wire transfers or custodian credits are confirmed.
     
  • Redemptions: T plus 0 queueing and burn request, followed by T plus 2 to T plus 30 depending on asset liquidity, portfolio unwind, and banking rails.
     
  • Key State Variables:
    • pendingDeposits - provisional mints awaiting off chain confirmation
    • queuedRedemptions - burn requests waiting for settlement liquidity
    • liquidityBuffer - reserved capital to fulfill redemptions immediately
    • shadowNAV - pre and post-settlement NAV values used to reconcile updates

Newww.svg

Legal Mapping: Tokens as Economic Instruments

In RWA systems, tokens represent economic rights, not direct ownership of the underlying asset. Treating tokens as derivatives reduces legal exposure and ensures alignment with regulatory frameworks. The smart-contract layer must mirror the rights, constraints, and processes defined in the governing legal documents (PSA, IPSA, or subscription agreements), using immutable parameters and oracle-verified references.

  • Token as Economic Right Tokens using ERC 3643 or ERC 1400 partitions encode claims issued by an SPV: yield entitlement, redemption priority, and distribution mechanics. They do not transfer legal title to the underlying asset.
  • SPV as the Legal Anchor

    1address public immutable spvEntity;
    2

    The SPV remains the holder of record in traditional systems. On-chain contracts reference off-chain title records, often through oracles fetching UCC filings or registry attestations.

  • Hybrid Redemption Logic On On-chain contracts handle requestRedeem and queue redemptions, while actual settlement occurs off-chain through deed transfers or wire instructions. Workflow: DocuSign signature - Oracle confirmation - final on-chain state.
  • Emergency Provisions

    1function emergencyPause() external onlyRole(REGULATOR_ROLE);
    2

    Mirrors emergency clauses in PSAs (for example, temporary suspension of transfers with a 72 hour notice period).

  • Failure Handling, If a custodian defaults or becomes non-operational, a migration path such as

    1migrateCustodian(newAddr)
    2

    emits a LegalEvent that downstream systems can use for insurance or SPV recovery claims.

Best Practice, store legal document references on IPFS and pinned their hashes in the contract:

1string public constant PSA_HASH = "ipfs://...";
2
3

Use UMA’s verification layer for court orders or regulator-mandated proofs. Maple’s 2025 architecture uses a Diamond proxy to implement legally required hotfixes without a full redeployment, ensuring near-perfect parity between contractual rights and code behavior.

Regulations Mapping
First RWA: Stablecoins
newsletter-poster

WE SECURE EVERYTHING YOU BUILD.

From day-zero risk mapping to exchange-ready audits — QuillAudits helps projects grow with confidence. Smart contracts, dApps, infrastructure, compliance — secured end-to-end.

DeFi SecurityplumeUniswap FoundationAethiropt-collectivePolygon SPNBNB Chain Kickstart

Office 104/105 Level 1, Emaar Square, Building 4 Sheikh Mohammed Bin Rashid Boulevard Downtown Dubai, United Arab Emirates P.O box: 416654

[email protected]

All Rights Reserved. © 2026. QuillAudits - LLC

Privacy Policy