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
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:
AssetRegistry with name, ISIN, valuation, and legal docs. The asset goes through off-chain verification. AssetNFT mints a unique ERC-721 token representing ownership. The NFT's metadata links to the asset's legal documents and appraisal. FractionalToken contract, which issues ERC-20 shares. A $5M property becomes 50,000 tradeable tokens. IdentityRegistry. ComplianceManager verifies jurisdiction and sanctions status. Only approved wallets can receive tokens. Vault. TransferManager validates each transfer against rules. Treasury collects protocol fees. Governance + Timelock manages protocol — adding assets, updating fees, freezing compromised positions, adjusting compliance rules. All changes have a timelock delay. 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
- Connect your wallet.
- Choose the contract type and parameters.
- Deploy and verify the contract.