|
| 1 | +--- |
| 2 | +title: Real World Asset (RWA) Token |
| 3 | +--- |
| 4 | + |
| 5 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa) |
| 6 | + |
| 7 | +Real World Asset (RWA) tokens are security tokens that represent ownership or rights to real-world assets |
| 8 | +such as real estate, commodities, securities, or other regulated financial instruments. |
| 9 | +These tokens must comply with various regulatory requirements including KYC/AML verification, transfer restrictions, |
| 10 | +and compliance rules. The RWA module provides a comprehensive framework based on the T-REX |
| 11 | +(Token for Regulated Exchanges) standard. |
| 12 | + |
| 13 | +## Overview |
| 14 | + |
| 15 | +The [RWA](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa) module provides a complete implementation of regulated security tokens with built-in compliance, |
| 16 | +identity verification, and administrative controls. The module is designed to be flexible and extensible, |
| 17 | +allowing integration with various identity registry and compliance frameworks. |
| 18 | + |
| 19 | +The RWA token extends the standard fungible token functionality with regulatory features required for |
| 20 | +security tokens, including: |
| 21 | + |
| 22 | +- **Identity Management**: Integration with identity registries for KYC/AML compliance |
| 23 | +- **Compliance Framework**: Modular compliance rules and validation for transfers and minting |
| 24 | +- **Transfer Controls**: Sophisticated transfer restrictions and validations |
| 25 | +- **Freezing Mechanisms**: Address-level and partial token freezing capabilities |
| 26 | +- **Recovery System**: Lost/old account recovery for verified investors |
| 27 | +- **Pausable Operations**: Emergency pause functionality for the entire token |
| 28 | +- **Role-Based Access Control (RBAC)**: Flexible privilege management for administrative functions |
| 29 | + |
| 30 | +## Architecture |
| 31 | + |
| 32 | +The RWA module follows a modular architecture that separates concerns and allows for flexible integration: |
| 33 | + |
| 34 | +### Core Components |
| 35 | + |
| 36 | +1. **RWA Token Contract**: The main token contract implementing the `RWAToken` trait, which extends both |
| 37 | +`FungibleToken` and `Pausable` traits. |
| 38 | + |
| 39 | +2. **Identity Verifier**: A separate contract responsible for verifying user identities. |
| 40 | +The RWA token expects the following function to be available: |
| 41 | +- `fn verify_identity(e: &Env, account: &Address);` |
| 42 | + |
| 43 | +3. **Compliance Contract**: A separate contract that validates transfers, minting, and burning operations. |
| 44 | +The RWA token expects the following functions to be available: |
| 45 | +- `fn can_transfer(e: &Env, from: Address, to: Address, amount: i128, token: Address) -> bool;` |
| 46 | +- `fn can_create(e: &Env, to: Address, amount: i128, token: Address) -> bool;` |
| 47 | +- `fn created(e: &Env, to: Address, amount: i128, token: Address);` |
| 48 | +- `fn destroyed(e: &Env, from: Address, amount: i128, token: Address);` |
| 49 | +- `fn transferred(e: &Env, from: Address, to: Address, amount: i128, token: Address);` |
| 50 | + |
| 51 | +This loose coupling between the RWA token and the modules allows the following: |
| 52 | +- Share identity verifier and compliance contracts across multiple RWA tokens |
| 53 | +- Implement custom identity verification approaches (Merkle trees, zero-knowledge proofs, claim-based, etc.) |
| 54 | +- Create modular compliance rules that can be composed and reused |
| 55 | + |
| 56 | +### Supporting Modules |
| 57 | + |
| 58 | +The module provides default implementations for common use cases: |
| 59 | + |
| 60 | +- **Claim Topics and Issuers**: Manages trusted claim issuers and claim types (e.g., KYC=1, AML=2) |
| 61 | +- **Identity Claims**: Integration with identity registries for cryptographic claim validation |
| 62 | +- **Identity Registry Storage**: Registry for storing identity information and country relations |
| 63 | +- **Claim Issuer**: Validates cryptographic claims with multiple signature schemes (Ed25519, Secp256k1, Secp256r1) |
| 64 | +- **Compliance**: Modular compliance framework with hook-based architecture |
| 65 | + |
| 66 | +## Usage |
| 67 | + |
| 68 | +We'll create a regulated security token for tokenized real estate shares. The token requires KYC verification, |
| 69 | +implements transfer restrictions, and provides administrative controls for compliance. |
| 70 | + |
| 71 | +Here's what a basic RWA token contract might look like (only the base token contract, not the modules): |
| 72 | + |
| 73 | +```rust |
| 74 | +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, String}; |
| 75 | +use stellar_access::access_control::{self as access_control, AccessControl}; |
| 76 | +use stellar_macros::default_impl; |
| 77 | +use stellar_tokens::{ |
| 78 | + fungible::{Base, FungibleToken}, |
| 79 | + rwa::{RWAToken, RWA}, |
| 80 | +}; |
| 81 | + |
| 82 | +#[contract] |
| 83 | +pub struct RealEstateToken; |
| 84 | + |
| 85 | +#[contractimpl] |
| 86 | +impl RealEstateToken { |
| 87 | + pub fn __constructor(e: &Env, admin: Address, manager: Address, initial_supply: i128) { |
| 88 | + // Set token metadata |
| 89 | + Base::set_metadata( |
| 90 | + e, |
| 91 | + 18, // 18 decimals |
| 92 | + String::from_str(e, "Real Estate Token"), |
| 93 | + String::from_str(e, "REST"), |
| 94 | + ); |
| 95 | + |
| 96 | + // Set up access control |
| 97 | + access_control::set_admin(e, &admin); |
| 98 | + |
| 99 | + // Create a "manager" role and grant it to the manager address |
| 100 | + access_control::grant_role_no_auth(e, &admin, &manager, &symbol_short!("manager")); |
| 101 | + |
| 102 | + // Mint initial supply to the admin (must be a verified identity) |
| 103 | + RWA::mint(e, &admin, initial_supply); |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +// Implement the FungibleToken trait with RWA contract type |
| 108 | +#[default_impl] |
| 109 | +#[contractimpl] |
| 110 | +impl FungibleToken for RealEstateToken { |
| 111 | + type ContractType = RWA; |
| 112 | +} |
| 113 | + |
| 114 | +// Implement the RWAToken trait for regulatory features |
| 115 | +#[default_impl] |
| 116 | +#[contractimpl] |
| 117 | +impl RWAToken for RealEstateToken {} |
| 118 | + |
| 119 | +// Implement AccessControl for role-based permissions |
| 120 | +#[default_impl] |
| 121 | +#[contractimpl] |
| 122 | +impl AccessControl for RealEstateToken {} |
| 123 | +``` |
| 124 | + |
| 125 | +## Key Features |
| 126 | + |
| 127 | +### Identity Verification |
| 128 | + |
| 129 | +Identity Verification is handled on a separate contract as a module. |
| 130 | + |
| 131 | +All token recipients must have verified identities before receiving tokens. The RWA token integrates |
| 132 | +with an identity verifier contract that validates user identities against cryptographic claims. |
| 133 | + |
| 134 | +```rust |
| 135 | +// Minting requires identity verification |
| 136 | +RWA::mint(e, &verified_investor, amount); |
| 137 | + |
| 138 | +// Transfers automatically verify recipient identity |
| 139 | +RWA::transfer(e, &from, &verified_recipient, amount); |
| 140 | + |
| 141 | +// Wallet recovery for lost/old accounts |
| 142 | +RWA::recover_balance(e, &old_account, &new_account, &operator); |
| 143 | +``` |
| 144 | + |
| 145 | +### Compliance Validation |
| 146 | + |
| 147 | +Compliance Validation is handled on a separate contract as a module. |
| 148 | + |
| 149 | +The compliance framework allows you to implement custom transfer and minting rules through a modular hook system: |
| 150 | + |
| 151 | +- **CanTransfer**: Validates if a transfer should be allowed |
| 152 | +- **CanCreate**: Validates if a mint operation should be allowed |
| 153 | +- **Transferred**: Updates state after a successful transfer |
| 154 | +- **Created**: Updates state after a successful mint |
| 155 | +- **Destroyed**: Updates state after a successful burn |
| 156 | + |
| 157 | +### Freezing Mechanisms |
| 158 | + |
| 159 | +Freezing Mechanisms are handled on the RWA token contract. |
| 160 | + |
| 161 | +RWA tokens support two types of freezing: |
| 162 | + |
| 163 | +1. **Address-level freezing**: Completely freeze an address from sending or receiving tokens |
| 164 | +2. **Partial token freezing**: Freeze a specific amount of tokens for an address |
| 165 | + |
| 166 | +```rust |
| 167 | +// Freeze an entire address |
| 168 | +RWA::set_address_frozen(e, &user_address, bool, &operator); |
| 169 | + |
| 170 | +// Freeze a specific amount of tokens |
| 171 | +RWA::freeze_partial_tokens(e, &user_address, amount, &operator); |
| 172 | + |
| 173 | +// Unfreeze tokens |
| 174 | +RWA::unfreeze_partial_tokens(e, &user_address, amount, &operator); |
| 175 | +``` |
| 176 | + |
| 177 | +### Recovery System |
| 178 | + |
| 179 | +Balance Recovery System is handled on the RWA token contract, whereas Identity Recovery System is handled |
| 180 | +on a separate contract as a module (may be a part of the Identity Registry contract). |
| 181 | + |
| 182 | +The recovery system allows authorized operators to transfer tokens from a lost/old account to a |
| 183 | +new account for the same verified investor: |
| 184 | + |
| 185 | +```rust |
| 186 | +// Recover tokens from old account to new account |
| 187 | +RWA::recover_balance(e, &old_account, &new_account, &operator); |
| 188 | +``` |
| 189 | + |
| 190 | +### Forced Transfers |
| 191 | + |
| 192 | +Forced Transfers are handled on the RWA token contract. |
| 193 | + |
| 194 | +Authorized operators can force transfers between verified wallets for regulatory compliance: |
| 195 | + |
| 196 | +```rust |
| 197 | +// Force a transfer for regulatory reasons |
| 198 | +RWA::forced_transfer(e, &from, &to, amount, &operator); |
| 199 | +``` |
| 200 | + |
| 201 | +## Modules |
| 202 | + |
| 203 | +The RWA package includes several supporting modules that work together to provide comprehensive regulatory compliance: |
| 204 | + |
| 205 | +### - Compliance |
| 206 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/compliance) |
| 207 | + |
| 208 | +This is a mandatory module, since RWA token contract expects the compliance checks and hooks to be available. |
| 209 | + |
| 210 | +The compliance module provides a modular framework for implementing custom compliance rules. |
| 211 | +It uses a hook-based architecture where compliance modules can be registered for specific events: |
| 212 | + |
| 213 | +- **Transferred**: Called after tokens are successfully transferred |
| 214 | +- **Created**: Called after tokens are successfully minted |
| 215 | +- **Destroyed**: Called after tokens are successfully burned |
| 216 | +- **CanTransfer**: Called during transfer validation (read-only) |
| 217 | +- **CanCreate**: Called during mint validation (read-only) |
| 218 | + |
| 219 | +The compliance contract is designed to be shared across multiple RWA tokens, with each hook function accepting a `token` parameter to identify the calling token. |
| 220 | + |
| 221 | +### - Identity Verifier |
| 222 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/identity_verifier) |
| 223 | + |
| 224 | +This is a mandatory module, since RWA token contract expects `verify_identity(e: &Env, address: Address)` function to be available. |
| 225 | + |
| 226 | +The identity verifier module provides the interface for verifying user identities. |
| 227 | +It also supports custom implementation approaches: |
| 228 | + |
| 229 | +- **Claim-based**: Cryptographic claims from trusted issuers (default implementation) |
| 230 | +- **Merkle Tree**: Efficient verification using merkle proofs |
| 231 | +- **Zero-Knowledge**: Privacy-preserving verification with custom ZK circuits |
| 232 | +- **Custom approaches**: Any implementation that satisfies the `verify_identity` interface |
| 233 | + |
| 234 | +The default claim-based implementation integrates with the Claim Topics and Issuers module and Identity Registry Storage. |
| 235 | + |
| 236 | +### - Claim Topics and Issuers |
| 237 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/claim_topics_and_issuers) |
| 238 | + |
| 239 | +This module is an implementation detail. It is provided as the suggested implementation for the `Claim-based` approach. |
| 240 | + |
| 241 | +Manages trusted claim issuers and claim topics (e.g., KYC=1, AML=2, Accredited Investor=3). This module: |
| 242 | + |
| 243 | +- Maintains a registry of trusted claim issuers |
| 244 | +- Defines which claim topics are required for token participation |
| 245 | +- Maps issuers to the claim topics they are authorized to issue |
| 246 | +- Can be shared across multiple RWA tokens |
| 247 | + |
| 248 | +### - Identity Registry Storage |
| 249 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/identity_registry_storage) |
| 250 | + |
| 251 | +This module is an implementation detail. It is provided as the suggested implementation for the `Claim-based` approach. |
| 252 | + |
| 253 | +Stores identity information for verified investors, including: |
| 254 | + |
| 255 | +- Mapping of wallet addresses to onchain identity contracts |
| 256 | +- Country information for regulatory compliance |
| 257 | +- Support for both individual and organizational identities |
| 258 | +- Recovery account mappings for lost wallet scenarios |
| 259 | + |
| 260 | +### - Identity Claims |
| 261 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/identity_claims) |
| 262 | + |
| 263 | +This module is an implementation detail. It is provided as the suggested implementation for the `Claim-based` approach. |
| 264 | + |
| 265 | +Manages on-chain identity claims with cryptographic signatures. Claims are issued by trusted authorities and contain: |
| 266 | + |
| 267 | +- Claim topic (e.g., KYC, AML) |
| 268 | +- Claim data (encrypted or hashed information) |
| 269 | +- Cryptographic signature |
| 270 | +- Issuer information |
| 271 | + |
| 272 | +### - Claim Issuer |
| 273 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/claim_issuer) |
| 274 | + |
| 275 | +This module is an implementation detail. It is provided as the suggested implementation for the `Claim-based` approach. |
| 276 | + |
| 277 | +Validates cryptographic claims with support for multiple signature schemes: |
| 278 | + |
| 279 | +- Ed25519 (Stellar native) |
| 280 | +- Secp256k1 (Ethereum compatible) |
| 281 | +- Secp256r1 (Enterprise PKI compatible) |
| 282 | + |
| 283 | +## Extensions |
| 284 | + |
| 285 | +The following optional extensions are provided: |
| 286 | + |
| 287 | +### - Document Manager |
| 288 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/extensions/doc_manager) |
| 289 | + |
| 290 | +This module is not mandatory. |
| 291 | + |
| 292 | +The `DocumentManager` trait extends the `RWAToken` trait to provide document management capabilities following the ERC-1643 standard. This extension allows contracts to: |
| 293 | + |
| 294 | +- Attach documents with URI, hash, and timestamp |
| 295 | +- Update existing document metadata |
| 296 | +- Remove documents from the contract |
| 297 | +- Retrieve individual or all documents |
| 298 | + |
| 299 | +This is useful for attaching legal documents, prospectuses, or other regulatory disclosures to the token contract. |
| 300 | + |
| 301 | +## Utility Modules |
| 302 | + |
| 303 | +### - Token Binder |
| 304 | +[Source Code](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/tokens/src/rwa/utils/token_binder) |
| 305 | + |
| 306 | +The `TokenBinder` trait provides a standardized interface for linking tokens to periphery contracts such as identity registries and compliance contracts. This allows a single periphery contract to serve multiple RWA tokens. |
| 307 | + |
| 308 | +Features: |
| 309 | +- Bind/unbind tokens to periphery services |
| 310 | +- Query all linked tokens |
| 311 | +- Efficient storage with bucket-based architecture (supports up to 10,000 tokens) |
| 312 | +- Swap-remove pattern for compact storage |
| 313 | + |
| 314 | +## Security Considerations |
| 315 | + |
| 316 | +When implementing RWA tokens, consider the following security aspects: |
| 317 | + |
| 318 | +1. **Authorization**: All administrative functions expect RBAC checks to be enforced on the `operator` parameter |
| 319 | +2. **Identity Verification**: Always verify identities before allowing token operations |
| 320 | +3. **Compliance Validation**: Ensure compliance rules are properly configured before enabling transfers |
| 321 | +4. **Freezing**: Use freezing mechanisms carefully as they can lock user funds |
| 322 | +5. **Recovery**: Recovery operations should have strict authorization and verification |
| 323 | +6. **Pausability**: The pause mechanism should only be accessible to authorized administrators |
| 324 | +7. **Contract Upgrades**: Consider using immutable periphery contracts or implementing upgrade mechanisms carefully |
0 commit comments