Skip to main content

RWA Tokenization Lab

Deploy smart contracts for Real-World Asset (RWA) POC projects. Connect your wallet, choose a contract template, and deploy on-chain.

⚠️ POC ONLY — Not for Production Use

Contracts deployed here are minimal and not audited. They are intended for rapid prototyping and testing only. Production deployments require professional smart contract audits, formal verification, and proper access controls. Never use these contracts to manage real user funds.

No wallet connected

Connect MetaMask or Rabby to deploy contracts

Contract Templates

ERC-20 Mirror Token

Fungible token mirroring off-chain assets (AAPL, AMZN, gold)

Use Case

Mirror asset prices as tradeable ERC-20 tokens for POC trading simulations.

Configure ERC-20 Mirror Token

Supply is in whole tokens. For 1M tokens with 18 decimals, the raw value will be 1,000,000 × 10¹⁸.
Connect wallet to deploy

RWA Tokenization — Deploy Smart Contracts On-Chain

Real-World Asset (RWA) tokenization is the process of representing physical and financial assets — real estate, stocks, commodities, bonds, art — as blockchain tokens. The global RWA market is projected to reach $16 trillion by 2030, driven by DeFi protocols, institutional adoption, and regulatory clarity. This lab lets you deploy the core smart contracts needed for an RWA project directly from your browser, with no backend or server required.

ERC-20 Mirror Tokens for Stocks & Commodities

Mirror tokens are ERC-20 fungible tokens that track the price of off-chain assets. For example, you can create mAAPL (Mirror AAPL), mAMZN (Mirror Amazon), mTSLA (Mirror Tesla), or mGOLD tokens. Each token is deployed with configurable parameters — name, symbol, decimals (6, 8, or 18), and initial supply. The deployer receives the full token supply and can distribute it to simulate trading, market making, or portfolio tracking.

In a production RWA system, mirror tokens integrate with oracle networks like Chainlink to fetch real-time price feeds, and compliance layers to enforce KYC/AML transfer restrictions. This POC tool handles the contract deployment so you can focus on building the trading and compliance logic.

Fractional Ownership Contracts

High-value assets — commercial real estate, fine art, private equity — are typically inaccessible to retail investors. Fractional ownership solves this by splitting an asset into thousands of fungible ERC-20 shares. For example, a $5M property can be split into 50,000 shares at $100 each, enabling micro-investment with low minimums.

This lab supports deploying fractional ownership contracts with configurable share token name, symbol, and total supply. In production, combine with governance contracts (like Snapshot or OpenZeppelin Governor) so shareholders can vote on property management decisions, sale events, and dividend distribution.

Custom Contract Deployment

Beyond the built-in templates, the Custom Bytecode tab lets you deploy any compiled smart contract. Compile your Solidity in Remix, Hardhat, or Foundry, then paste the bytecode and constructor arguments. The tool ABI-encodes the constructor arguments automatically using viem and sends the deployment transaction through your connected wallet.

Supported Blockchains & Wallets

The RWA Tokenization Lab supports deployment to all major EVM-compatible blockchains:

  • Ethereum Mainnet and Sepolia testnet
  • Polygon and Mumbai testnet
  • Arbitrum One and Arbitrum Sepolia
  • Base and Base Sepolia
  • Optimism

Wallet connections are handled via the EIP-1193 standard, supporting MetaMask and Rabby Wallet. The tool auto-detects installed wallets, displays the connected chain, and shows deployed contract addresses with direct links to block explorers (Etherscan, Polygonscan, Arbiscan, Basescan, OP Scan).

How RWA Tokenization Works

1. Asset Selection

Choose a real-world asset to tokenize — stocks (AAPL, TSLA, AMZN), real estate, commodities (gold, silver), or bonds.

2. Contract Deployment

Deploy an ERC-20 mirror token or fractional ownership contract on your chosen blockchain using this lab.

3. Price Oracle Integration

Connect the token to a price feed (Chainlink, Pyth Network, API3) so the on-chain token reflects real-world market prices.

4. Trading & Liquidity

List the token on a DEX (Uniswap, SushiSwap) or create an order book for POC trading simulation.

Frequently Asked Questions

What is RWA tokenization?

RWA tokenization is the process of issuing blockchain tokens that represent ownership or rights to real-world assets like real estate, stocks, commodities, and bonds. These tokens can be traded, transferred, and programmed with smart contract logic.

Is this tool safe to use?

This tool deploys minimal smart contracts that are not audited. It is intended for POC (proof of concept) development only. For production deployments, always use professionally audited contracts from OpenZeppelin or similar libraries.

Which wallets are supported?

The tool supports any EIP-1193 compatible wallet including MetaMask and Rabby. It auto-detects the installed wallet and connects with a single click.

Can I deploy on any blockchain?

Yes — any EVM-compatible chain works. The tool shows the connected chain name and provides block explorer links for deployed contracts on Ethereum, Polygon, Arbitrum, Base, and Optimism.

What is a mirror token?

A mirror token is an ERC-20 token that tracks the price of an off-chain asset. For example, mAAPL mirrors Apple stock price. Mirror tokens are used in synthetic asset protocols and RWA trading simulations.

What is fractional ownership?

Fractional ownership splits a high-value asset into smaller, tradeable shares. For example, a $1M property can be split into 10,000 ERC-20 tokens at $100 each, allowing multiple investors to own a fraction of the asset.

RWA Tokenization Use Cases

  • Stock mirroring — Create ERC-20 tokens that track AAPL, TSLA, AMZN, GOOGL prices for POC trading
  • Real estate tokenization — Represent property deeds as tokens with fractional ownership
  • Commodity tokens — Tokenize gold, silver, oil, or agricultural products
  • Bond tokenization — Issue tokenized bonds with programmable coupon payments
  • Invoice financing — Tokenize outstanding invoices for DeFi lending protocols
  • Carbon credits — Tokenize verified carbon offsets for transparent trading
  • Private equity — Tokenize fund shares for simplified investor onboarding

TokenizationFactory — The Factory Pattern for RWA Contracts

A TokenizationFactory is a smart contract that deploys new tokenized assets on-demand. Instead of manually deploying individual ERC-20, fractional ownership, or custom tokenization contracts each time, a factory contract lets you call a single function like createAsset("AAPL", "mAAPL", 1000000) and it deploys a new token contract, registers it, and returns the address — all in one transaction.

How a TokenizationFactory Works:

pragma solidity ^0.8.0;

interface IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function totalSupply() external view returns (uint256);
}

contract MirrorToken {
    // ... ERC-20 implementation ...
    constructor(string memory _name, string memory _symbol, uint256 _supply, address _creator) {
        // Mint tokens to creator
    }
}

contract TokenizationFactory {
    address[] public deployedTokens;
    mapping(address => string[]) public creatorAssets;

    event TokenCreated(address indexed token, address indexed creator, string name, string symbol);

    function createAsset(
        string memory name,
        string memory symbol,
        uint256 supply
    ) external returns (address) {
        MirrorToken newToken = new MirrorToken(name, symbol, supply, msg.sender);
        address tokenAddr = address(newToken);
        deployedTokens.push(tokenAddr);
        creatorAssets[msg.sender].push(name);
        emit TokenCreated(tokenAddr, msg.sender, name, symbol);
        return tokenAddr;
    }

    function getDeployedTokens() external view returns (address[] memory) {
        return deployedTokens;
    }

    function getTokenCount() external view returns (uint256) {
        return deployedTokens.length;
    }
}

Factory Benefits

  • • Deploy new tokens in a single transaction
  • • Track all deployed assets on-chain
  • • Consistent contract initialization
  • • Lower gas vs multiple separate deploys
  • • Indexable event logs for UI integration

Factory Use Cases

  • • Launch a basket of mirror tokens (AAPL, AMZN, TSLA)
  • • Create fractional shares for multiple properties
  • • Batch-deploy commodity tokens (gold, silver, oil)
  • • Spin up tokenized bond series
  • • Onboard new assets without writing more code

To deploy a TokenizationFactory using this lab, compile the Solidity above in Remix IDE or Hardhat, then paste the bytecode into the Custom Bytecode tab. Once deployed, call createAsset() from your wallet to launch new tokenized assets without deploying separate contracts each time.

Factory Pattern vs Individual Deployment

This lab supports both approaches. For a single mirror token, deploy directly using the ERC-20 Mirror Token template. For projects that need multiple tokenized assets — say a basket of 10 stocks or a portfolio of 5 properties — deploy a TokenizationFactory once, then call createAsset() for each new token. The factory pattern reduces gas costs, ensures consistent deployment, and gives you a single on-chain registry of all your tokenized assets.

Complete RWA Architecture — Contract Stack

A production-grade RWA tokenization platform requires more than just token contracts. Below is the full contract stack, from asset onboarding to user trading, with each contract's role explained. Use this as a blueprint for your POC project.

  ┌─────────────────────────────────────────────────────────────────────┐
  │                        RWA TOKENIZATION STACK                       │
  └─────────────────────────────────────────────────────────────────────┘

  Real-World Asset (AAPL stock, Property, Gold, Bond)
    │
    ▼
  ┌──────────────────┐
  │  AssetRegistry    │  ← Registers asset metadata, status, valuation
  └────────┬─────────┘
    │
    ▼
  ┌──────────────────┐
  │  AssetNFT (721)   │  ← Mints unique NFT representing ownership deed
  └────────┬─────────┘
    │
    │ Fractionalize
    ▼
  ┌──────────────────┐
  │ FractionalToken   │  ← ERC-20 shares representing fractional ownership
  │    (ERC-20)       │
  └────────┬─────────┘
    │
    │ Users Buy / Sell
    ▼
  ┌──────────────────┐
  │  Vault            │  ← Custody contract — holds assets & settles trades
  └────────┬─────────┘
    │
    ├──────────────────┬───────────────────┬────────────────────┐
    ▼                  ▼                   ▼                    ▼
  ┌──────────┐  ┌──────────────┐  ┌───────────────┐  ┌──────────────┐
  │Compliance│  │   Transfer   │  │   Identity    │  │  Treasury   │
  │ Manager  │  │   Manager   │  │   Registry    │  │              │
  │ KYC/AML  │  │  Restricts  │  │  Maps wallets │  │  Collects   │
  │ Sanctions│  │  transfers  │  │  to verified  │  │  protocol   │
  │ Jurisdict│  │  to approved│  │  identities   │  │  fees       │
  └────┬─────┘  │   wallets   │  └───────────────┘  └──────┬───────┘
       │        └──────────────┘                            │
       └────────────┬───────────────────────────────────────┘
                    ▼
              ┌───────────┐
              │ Governance│  ← DAO / admin controls protocol parameters
              │  +Timelock│     All admin actions delayed by timelock
              └───────────┘
        

1. AssetRegistry — Asset Onboarding

The entry point for any RWA project. When a real-world asset is brought on-chain, the AssetRegistry stores its metadata — asset name, ISIN/CUSIP identifier, description, valuation, legal docs URI, and status (pending, active, frozen, delisted). It acts as the source of truth for what assets exist and whether they're tradeable.

contract AssetRegistry {
  struct Asset {
    string name;        // "Apple Inc. Common Stock"
    string symbol;      // "AAPL"
    string isin;        // "US0378331005"
    uint256 valuation;  // in USD (oracle-updated)
    AssetStatus status; // Pending, Active, Frozen, Delisted
    string metadataURI; // IPFS/Arweave link to legal docs
  }

  mapping(uint256 => Asset) public assets;
  uint256 public assetCount;

  function registerAsset(
    string memory name, string memory symbol,
    string memory isin, uint256 valuation, string memory uri
  ) external onlyAdmin returns (uint256 assetId);

  function updateValuation(uint256 assetId, uint256 newValuation) external onlyOracle;
  function freezeAsset(uint256 assetId) external onlyAdmin;
}

2. AssetNFT (ERC-721) — Ownership Deed

Once an asset is registered, an NFT is minted representing the ownership deed. For a property, this is the digital title. For a stock mirror, it represents the basket backing. Each NFT links back to the AssetRegistry via its assetId and stores a token URI with full metadata — property address, photos, legal description, appraisal reports.

contract AssetNFT is ERC721 {
  uint256 public nextTokenId;
  mapping(uint256 => uint256) public tokenToAssetId; // NFT → AssetRegistry ID

  function mint(address to, uint256 assetId, string memory tokenURI)
    external onlyAssetRegistry returns (uint256);

  function burn(uint256 tokenId) external onlyVault; // redeem/burn on exit
}

3. FractionalToken (ERC-20) — Fractional Ownership

High-value NFTs are illiquid. Fractionalization wraps the NFT and issues fungible ERC-20 shares against it. A $5M property NFT can be split into 50,000 tokens at $100 each. Shareholders can trade on DEXs, and governance decides when to sell the underlying asset and distribute proceeds.

contract FractionalToken is ERC20 {
  uint256 public nftTokenId;     // The NFT this token fractionalizes
  address public nftContract;    // AssetNFT address

  constructor(
    string memory name, string memory symbol,
    uint256 totalShares, address _nftContract, uint256 _nftTokenId
  ) {
    _mint(msg.sender, totalShares);
    nftContract = _nftContract;
    nftTokenId = _nftTokenId;
  }

  // Override transfer to check compliance
  function _update(address from, address to, uint256 amount)
    internal override(IERC20, ERC20) {
    require(IComplianceManager(compliance).canTransfer(from, to), "Transfer not allowed");
    super._update(from, to, amount);
  }
}

4. Vault — Asset Custody & Settlement

The Vault is the custody contract. It holds the actual NFTs and tokenized assets. When users buy fractional tokens, payment flows through the Vault. When an asset is sold or redeemed, the Vault distributes proceeds. It's the financial backbone — all value flows through it.

contract Vault {
  address public governance;
  address public treasury;
  uint256 public protocolFeeBps = 50; // 0.5%

  mapping(address => uint256) public balances;

  function deposit(address token, uint256 amount) external payable;
  function withdraw(address token, uint256 amount) external onlyGovernance;

  // Buy fractional tokens: payment in → tokens out
  function buyShares(address fractionalToken, uint256 shareAmount)
    external returns (bool);

  // Sell fractional tokens: tokens in → payment out (minus fee)
  function sellShares(address fractionalToken, uint256 shareAmount)
    external returns (bool);

  // Redeem: burn tokens, claim proportional asset proceeds
  function redeem(address fractionalToken, uint256 shareAmount)
    external returns (uint256 payout);
}

5. ComplianceManager — KYC/AML, Sanctions, Jurisdiction

The ComplianceManager enforces regulatory rules on every transfer. It checks three things: (a) KYC/AML status — are both sender and receiver verified? (b) Sanctions screening — is either address on a sanctions list (OFAC, UN, EU)? (c) Jurisdiction rules — are cross-border transfers between these jurisdictions allowed? Every token transfer calls canTransfer() before executing.

contract ComplianceManager {
  enum KYCStatus { None, Pending, Verified, Rejected, Revoked }

  mapping(address => KYCStatus) public kycStatus;
  mapping(address => bool) public isSanctioned;
  mapping(address => bytes2) public jurisdiction; // country code
  mapping(bytes2 => mapping(bytes2 => bool)) public allowedCorridors;

  // Called by token contracts before transfer
  function canTransfer(address from, address to)
    external view returns (bool)
  {
    if (isSanctioned[from] || isSanctioned[to]) return false;
    if (kycStatus[from] != KYCStatus.Verified) return false;
    if (kycStatus[to] != KYCStatus.Verified) return false;

    bytes2 fromCountry = jurisdiction[from];
    bytes2 toCountry = jurisdiction[to];
    if (!allowedCorridors[fromCountry][toCountry]) return false;

    return true;
  }

  function setKYC(address user, KYCStatus status) external onlyAdmin;
  function setSanctioned(address user, bool sanctioned) external onlyAdmin;
  function setJurisdiction(address user, bytes2 country) external onlyAdmin;
  function allowCorridor(bytes2 from, bytes2 to) external onlyAdmin;
}

6. TransferManager — Transfer Restrictions

While ComplianceManager checks who can transact, TransferManager restricts how tokens move. It enforces transfer limits (max tokens per transaction), lock-up periods (vesting), allowlists/blocklists, and per-token transfer rules. Think of it as the traffic controller for token movements.

contract TransferManager {
  mapping(address => bool) public isApprovedWallet; // allowlist
  mapping(address => uint256) public maxTransferAmount;
  mapping(address => uint256) public lockupUntil;   // timestamp

  struct TransferRule {
    bool requireAllowlist;
    bool requireCompliance;
    uint256 maxPerTx;
    uint256 cooldownPeriod;
  }

  mapping(address => TransferRule) public tokenRules; // per-token config

  function validateTransfer(
    address token, address from, address to, uint256 amount
  ) external view returns (bool) {
    TransferRule memory rule = tokenRules[token];
    if (rule.requireAllowlist) {
      require(isApprovedWallet[from] && isApprovedWallet[to], "Not approved");
    }
    if (rule.maxPerTx > 0 && amount > rule.maxPerTx) return false;
    if (block.timestamp < lockupUntil[from]) return false;
    return true;
  }

  function approveWallet(address wallet) external onlyAdmin;
  function setTokenRules(address token, TransferRule memory rules) external onlyAdmin;
}

7. IdentityRegistry — Wallet-to-Identity Mapping

Maps each wallet address to a verified identity record — legal name, entity type (individual, corporate, institutional), jurisdiction, accreditation status, and a hash of off-chain KYC documents. This is the bridge between on-chain addresses and real-world legal entities, required for regulated RWA transfers.

contract IdentityRegistry {
  enum EntityType { Individual, Corporate, Institutional, Government }

  struct Identity {
    bytes32 identityHash;     // hash of legal documents (stored off-chain)
    EntityType entityType;
    bytes2 jurisdiction;      // country code
    bool isAccredited;        // accredited investor status
    uint256 verifiedAt;       // timestamp of KYC verification
    address delegate;         // authorized delegate (e.g., fund manager)
  }

  mapping(address => Identity) public identities;
  mapping(bytes32 => address) public hashToWallet; // prevent duplicate identities

  function registerIdentity(
    bytes32 identityHash, EntityType entityType,
    bytes2 jurisdiction, bool isAccredited
  ) external onlyKYCAuthority returns (bool);

  function getIdentity(address wallet)
    external view returns (Identity memory);

  function isVerified(address wallet) external view returns (bool);
}

8. Treasury — Protocol Fee Collection

Collects protocol fees from every trade, redemption, and asset registration. Fees are configurable by Governance and can be routed to a treasury multisig, DAO treasury, or used for token buybacks. The Treasury contract is where protocol revenue accumulates.

contract Treasury {
  address public governance;
  address public multisig;           // where funds are sent
  uint256 public tradeFeeBps = 30;   // 0.3% per trade
  uint256 public redemptionFeeBps = 50; // 0.5% on redemption

  mapping(address => uint256) public collectedByToken; // fee tracking

  function collectFee(address token, uint256 amount, address payer)
    external onlyVault {
    collectedByToken[token] += amount;
    // Transfer fee to treasury multisig
    IERC20(token).transfer(multisig, amount);
  }

  function setTradeFee(uint256 bps) external onlyGovernance;
  function withdraw(address token, uint256 amount) external onlyMultisig;
}

9. Governance + Timelock — DAO / Admin Controls

Governance controls protocol parameters — fee rates, compliance rules, allowed jurisdictions, sanctioned addresses, and asset listings. It can be a simple multisig for POC or a full DAO with token-weighted voting for production. The Timelock ensures no admin action takes effect immediately — every change has a delay (e.g., 48 hours), giving users time to react or exit if they disagree with a decision.

contract Governance {
  address[] public admins;
  uint256 public requiredSignatures; // multisig threshold
  mapping(bytes32 => uint256) public proposalVotes;
  mapping(bytes32 => bool) public executed;

  function propose(bytes32 proposalId, address target, bytes memory callData)
    external onlyAdmin;

  function vote(bytes32 proposalId) external onlyAdmin;
  function execute(bytes32 proposalId) external onlyAfterTimelock;
}

contract Timelock {
  uint256 public delay = 2 days; // all actions wait 48 hours

  mapping(bytes32 => uint256) public queuedAt; // when was action queued

  function queue(address target, bytes memory data)
    external onlyGovernance returns (bytes32 txId);

  function execute(address target, bytes memory data)
    external returns (bytes memory result)
  {
    bytes32 txId = keccak256(abi.encode(target, data));
    require(block.timestamp >= queuedAt[txId] + delay, "Timelock not expired");
    (bool ok, bytes memory result) = target.call(data);
    require(ok, "Execution failed");
  }
}

End-to-End RWA Tokenization Flow

The full lifecycle of a real-world asset on-chain, step by step:

1
Asset Onboarding: Admin registers the real-world asset in AssetRegistry with name, ISIN, valuation, and legal docs. The asset goes through off-chain verification.
2
NFT Minting: AssetNFT mints a unique ERC-721 token representing ownership. The NFT's metadata links to the asset's legal documents and appraisal.
3
Fractionalization: The NFT is deposited into FractionalToken contract, which issues ERC-20 shares. A $5M property becomes 50,000 tradeable tokens.
4
Identity & Compliance Check: Users complete KYC via IdentityRegistry. ComplianceManager verifies jurisdiction and sanctions status. Only approved wallets can receive tokens.
5
Trading: Users buy/sell fractional tokens through the Vault. TransferManager validates each transfer against rules. Treasury collects protocol fees.
6
Governance: Governance + Timelock manages protocol — adding assets, updating fees, freezing compromised positions, adjusting compliance rules. All changes have a timelock delay.
7
Redemption: If the asset is sold (e.g., property sold at auction), the Vault burns fractional tokens and distributes proportional proceeds to shareholders.

About the RWA Deploy Lab

Deploy real-world asset (RWA) smart contracts from your browser. Create ERC-20 mirror tokens, fractional ownership contracts, and custom tokenization.

Connect MetaMask or Rabby, configure your token parameters, and deploy on Ethereum, Polygon, Arbitrum, Base, or Optimism. A POC tool for RWA developers.

How to use

  1. Connect your wallet.
  2. Choose the contract type and parameters.
  3. Deploy and verify the contract.