Non-EVM Standards
Solana sRFC 00020
Learn how Solana sRFC 00020 standardizes RWA and security tokens with compliance rules, transfer restrictions and asset controls.
sRFC 00020, the proposed RWA/Security Token Standard, defines a modular, open-source framework for permissioned tokens on Solana, enabling verifiable ownership and compliance features directly integrated with Token-2022 extensions for assets like real estate, equities, or commodities. For Real World Asset (RWA) protocols, this standard is especially valuable, as tokens can represent fractional claims on tokenized properties, securities, or debt instruments while maintaining a compliant, interoperable interface for issuance, transfers, clawbacks, and distributions without bespoke program development.
Before sRFC 00020, Solana RWA projects patched compliance onto Token-2022 or Metaplex metadata, leading to inconsistent verification, fragmented regulatory tools, and high integration costs. sRFC 00020 resolved this by proposing a unified, extensible standard with commoditized and securitized variants, leveraging oracles for title proofs and hooks for dynamic rules. For RWA builders, the standard provides a flexible abstraction layer supporting off-chain document verification, oracle-fed updates, and asynchronous escrow releases, while enabling composability with Solana DeFi like Jupiter or lending protocols.
A key design principle is variant-based modularity, where tokens expose standardized Token-2022 interfaces augmented by RWA-specific modules without exposing internal verifier logic. This is well suited to RWA tokens where ownership may depend on off-chain legal data or regulatory halts, yet integrators like wallets or aggregators still need reliable, auditable flows.
Use of sRFC 00020 in RWA Contexts
sRFC 00020 is the foundational proposed standard for compliant RWA tokens on Solana because it abstracts the complexity of securitizing and managing real-world assets into an extensible, Token-2022-compatible framework. While traditional DeFi tokens use basic SPL for unrestricted transfers, RWA tokens adapt the model to regulated, illiquid assets, tokenized real estate, private equity, commodities, or bond portfolios, where on-chain tokens represent legally backed off-chain value held by custodians or SPVs, with built-in verifiers for securities laws like Reg D or MiCA.
Key Applications in RWA Development
Fractional Ownership and Liquidity Provision
sRFC 00020 allows developers to mint fungible tokens proportional to deposits, unlocking fractional ownership and secondary-market liquidity under compliance rules.
- Implement
mintvia Issuer Whitelist with title verification to confirm ownership. - Tokens can trade freely within whitelisted parties on DEXs, offering liquidity for assets that would otherwise be locked for years.
- Example: A real estate token where title status embeds lien checks, and transfer rules restrict to accredited groups.
Yield Accrual and NAV Management
Dividend mechanisms automate income distribution (e.g., rental yields from property tokens), with snapshots querying oracles (e.g., Pyth) for historical holdings. This supports merkle-based claiming without manual interventions, ideal for tokenized securities or funds.
Using trusted sources (Pyth, Switchboard) ensures accurate verifications, critical for compliance and for investor claims. Regulators increasingly expect transparent ownership reporting, and the standard provides this without exposing internal oracle state.
Redemption and Settlement Mechanics
RWA redemptions are inherently asynchronous, as physical settlement layers (banks, custodians, transfer agents) cannot finalize instantly.
Patterns include:
burnwith escrow for queued releases.- Clawback hooks for invalid transfers.
- Memo-required events for signed claims.
- Proof-of-title checks before fulfillment.
These guardrails prevent unauthorized burns and ensure token solvency, especially for semi-liquid assets like private equity or T-bills.
Composability Across the RWA Stack
sRFC 00020 tokens plug directly into Solana DeFi:
- Marginfi accepts tokens as collateral within whitelist restrictions.
- Jupiter pairs can provide deep secondary liquidity for permitted transfers.
- Aggregators (e.g., Kamino) route into the standard natively.
For regulated RWAs:
- Pair with secondary trading whitelists for investor eligibility gating.
- Combine with escrow for modular settlements.
- Integrate identity proofs via title verifiers.
This drastically reduces integration complexity, for example, a tokenized property token can list across lending markets without custom adapters.
Developer Advantages in RWA Builds
- Regulatory Alignment: Variant modules hide off-chain legal processes while preserving accurate verifiers for MiFID II/MiCA-aligned disclosures.
- Extensibility: Hooks and oracles allow injecting RWA-specific logic i.e., title proofs, geofencing, or Arweave-pinned compliance docs.
- Risk Isolation: Tokens remain fully Token-2022 compliant, halts do not impact wallet-held balances outside rules.
- Upgrade Path: Existing SPL tokens can migrate via adapters, preserving TVL and simplifying audits.
To visualize the end-to-end flow in an RWA token, the following sequence diagram captures the typical mint - transfer - burn cycle. It illustrates how users interact with the token mint, how modules interact with hooks and oracles, and how off-chain verification updates flow back on-chain through checks or memos. This representation is especially important for understanding asynchronous transfers, delayed settlements, and verifier-driven compliance in RWA systems.
This diagram highlights how sRFC 00020 acts as the connective tissue between on-chain token operations and off-chain asset realities. Mints enforce verifications proportional to contributed value, hooks capture real-world compliance as transfers execute, and escrow functions help manage distributions during burns. For illiquid RWA portfolios, the model can be extended with explicit rule modules between the mint (M) and the custodian or SPV (C) to handle delayed settlement cycles.
Core Specification
An sRFC 00020 mint must implement the core Token-2022 interface for its fungible structure, the permissioned representation of a user’s proportional claim on the underlying asset. Optional variants enable advanced features like title proofs, a valuable enhancement for RWA use cases where institutions manage ownership without needing full custom programs.
In sRFC 00020, the mint behaves like any Token-2022 token (balance queries, total supply, transfers), while variants refer to appended modules for collateral management via hooks. The specification enforces a clean separation between base tokens and verifier modules, ensuring predictable operations and seamless integration across Solana and RWA systems.
Key Definitions
- Mint: The Token-2022 configuration with verifier extension data, e.g., a tokenized property or equity instrument.
- Account: The token balance holder, extensible for whitelist assignments or halts.
- Total Supply: The aggregate token value managed by the mint, equal to the sum of principal, distributed dividends, and adjustments for fees or clawbacks.
- Variant Modules: (e.g., Title Verifier, Clawback Hook) Provide idealized, rule-agnostic behaviors for UI, analytics, and oracle integrations. They represent the legal relationship between base tokens and enforced logic.
- Hook Functions: (e.g., execute transfer) Provide near-exact estimates of expected outcomes, reflecting rules, rounding, or title changes, without executing state updates. These enable accurate transaction planning.
- Rounding Rules: sRFC 00020 mandates rounding in favor of the mint:
- Round down when issuing tokens or deductions, preventing dilution.
- Round up when applying halts or requirements, protecting existing participants. These rules ensure fair distribution and discourage precision-based attacks.
The sRFC 00020 standard defines two variants with 15+ instructions, organized by their roles in verification, restrictions, escrow, and dividends. Every module integrates at deployment, ensuring a single source of truth for token behavior and movements. Below is the Rust-equivalent interface, accompanied by developer notes covering edge cases, rounding behavior, and considerations specific to RWA tokens such as asynchronous hooks and oracle-driven updates.
1use anchor_lang::prelude::*;
2use anchor_spl::token_2022::{self, Token2022};
3
4declare_id!("Srfc00020RWA9jKnMhdjdxXg2ZNTS3YnMGYdwJkBHnezMJwr3"); // Proposed ID
5
6#[program]
7pub mod srfc_00020 {
8 use super::*;
9
10 // Commoditized Variant: Title Handling
11 pub fn initialize_title_verifier(
12 ctx: Context<InitializeTitleVerifier>,
13 property_address: String,
14 square_footage: u64,
15 ) -> Result<()> {
16 // Set metadata
17 Ok(())
18 }
19
20 pub fn update_property_info(
21 ctx: Context<UpdatePropertyInfo>,
22 new_address: String,
23 renovations: Vec<String>,
24 ) -> Result<()> {
25 // Oracle-signed update
26 Ok(())
27 }
28
29 // Securitized Variant: Compliance Tools
30 pub fn initialize_securitized_token(
31 ctx: Context<InitializeSecuritized>,
32 whitelist_issuers: Vec<Pubkey>,
33 whitelist_traders: Vec<Pubkey>,
34 ) -> Result<()> {
35 // Setup lists
36 Ok(())
37 }
38
39 pub fn clawback_transaction(
40 ctx: Context<Clawback>,
41 tx_signature: [u8; 64],
42 reason: String,
43 ) -> Result<()> {
44 // Reverse transfer
45 Ok(())
46 }
47
48 pub fn halt_trading(
49 ctx: Context<HaltTrading>,
50 duration: i64,
51 condition: u8,
52 ) -> Result<()> {
53 // Pause flag
54 Ok(())
55 }
56
57 pub fn escrow_funds(
58 ctx: Context<EscrowFunds>,
59 amount: u64,
60 release_condition: u64,
61 ) -> Result<()> {
62 // Hold until met
63 Ok(())
64 }
65
66 pub fn verify_regulatory_filing(
67 ctx: Context<VerifyFiling>,
68 filing_hash: [u8; 32],
69 compliance_type: u8, // e.g., Reg D
70 ) -> Result<()> {
71 // Oracle check
72 Ok(())
73 }
74
75 pub fn distribute_dividends(
76 ctx: Context<DistributeDividends>,
77 merkle_root: [u8; 32],
78 total_amount: u64,
79 ) -> Result<()> {
80 // Schedule setup
81 Ok(())
82 }
83
84 pub fn update_dividend_schedule(
85 ctx: Context<UpdateSchedule>,
86 new_frequency: u64,
87 ) -> Result<()> {
88 // Modify params
89 Ok(())
90 }
91
92 // Core Transfer with Variant Hook
93 pub fn execute_rwa_transfer(
94 ctx: Context<ExecuteRwaTransfer>,
95 amount: u64,
96 variant: u8, // 0=Commoditized, 1=Securitized
97 ) -> Result<()> {
98 // Invoke verifier, rules
99 Ok(())
100 }
101
102 #[event]
103 pub struct TransferEvent {
104 pub amount: u64,
105 pub from: Pubkey,
106 pub to: Pubkey,
107 pub variant: u8,
108 pub title_verified: bool,
109 }
110
111 #[event]
112 pub struct ClawbackEvent {
113 pub tx_signature: [u8; 64],
114 pub reason: String,
115 }
116}
Detailed Function Breakdown
Below is a module-by-module explanation of the sRFC 00020 interface, including edge cases, rounding behavior, and RWA-specific implementation guidance for regulated assets, off-chain settlement, and hook-driven validation.
initialize_title_verifier()
Sets up commoditized variant with initial property data linked to Arweave metadata. In RWA tokens, this pins the ownership proof for tokenized properties, deeds, or commodity certificates.
- This config is updatable only by trusted oracles to avoid unauthorized changes.
update_property_info()
Appends oracle-signed changes to metadata (e.g., renovations affecting valuation).
- RWA Integration: For compliance-based assets, tie to real estate oracles (Pyth / Switchboard).
- Edge Case: Must handle multi-lien resolutions or historical audits.
initialize_securitized_token()
Appends whitelists for issuers/traders in securitized variant.
- Formula: Lists as dynamic PDAs for scalability.
- Usage: Onboarding dashboards, risk analytics.
- RWA Note: Reflects pure regulatory mapping, does not account for escrow overrides.
clawback_transaction()
Reverses a prior transfer with issuer approval and reason log.
- Ensures no precision-based arbitrage on reversals.
- RWA Note: Useful for hack recoveries or compliance violations in regulated markets.
halt_trading()
Activates global pause with timed conditions (e.g., regulatory review).
- Return max for “no limit” on pause depth.
- RWA Note: Enforce temporary halts due to filing flags or market events.
escrow_funds()
Locks amount until condition (e.g., title transfer) via oracle.
- Discrepancies vs base transfer reveal lock impact.
- RWA Note: Useful for quote generation in settlement-heavy tokens or those with custody fees.
verify_regulatory_filing()
Confirms filing hash against oracle for compliance (e.g., SEC docs).
- Requires prior whitelist check.
- Includes hooks for AML evaluation.
- RWA Note:
- For illiquid assets (such as real estate and private equity): pair with clawback asynchronous resolutions.
- Trigger oracle checks for jurisdiction validation.
distribute_dividends, update_dividend_schedule
Merkle root setup and param adjustments for income snapshots.
- distribute(total_amount) requires exact root; tokens distributed post-verification.
- RWA Use Case: Rental sharing where holders claim fixed amounts based on holdings.
Reference Implementation
The proposed sRFC 00020 offers a conceptual, community-audited foundation for building compliant tokens, extending Token-2022 with RWA modules. Its design encourages minimal overrides while still supporting custom verifier models, whitelist configs, escrow layers, and oracle integration.
Key capabilities include:
- Inflation Attack Protection: The implementation prevents dilution by enforcing whitelist mints and oracle checks. Early issuers cannot exploit low-supply corner cases to extract excess value.
- Rounding Compliance: All verifications use checked arithmetic for precise, deterministic operations that adhere to Token-2022 requirements of rounding in favor of the mint. This eliminates subtle precision-drift exploits.
- Extensible Hooks: Lifecycle hooks such as execute_rwa_transfer allow developers to embed RWA-specific functionality, title oracle checks, compliance gating, settlement status validation, or dividend accounting, without modifying core logic.
- Flexible Structure: The variants build on Anchor’s base, with optional multi-sig or access controls for regulated administration. This makes it straightforward to integrate custodial controls, upgrade pathways, or role-gated operations required in regulated RWA environments.
1use anchor_lang::prelude::*;
2use anchor_spl::token_2022::{self, Token2022};
3
4declare_id!("Srfc00020RWA9jKnMhdjdxXg2ZNTS3YnMGYdwJkBHnezMJwr3");
5
6#[program]
7pub mod srfc_00020_rwa {
8 use super::*;
9
10 pub fn initialize_commoditized_token(
11 ctx: Context<InitializeCommoditized>,
12 property_address: String,
13 initial_metadata_uri: String,
14 ) -> Result<()> {
15 let verifier = &mut ctx.accounts.verifier;
16 verifier.variant = 0; // Commoditized
17 verifier.title_owner = ctx.accounts.issuer.key();
18 verifier.metadata_uri = initial_metadata_uri;
19 verifier.property_address = property_address;
20 Ok(())
21 }
22}
23
24#[derive(Accounts)]
25pub struct InitializeCommoditized<'info> {
26 #[account(init, payer = payer, space = 8 + 32 + 200 + 100)]
27 pub verifier: Account<'info, TitleVerifier>,
28 #[account(mut)]
29 pub payer: Signer<'info>,
30 pub system_program: Program<'info, System>,
31 // ...
32}
- The initializer pins variant at creation. For RWA tokens, prefer oracle-signed metadata and link to Arweave for provenance.
- URI can be extended for custom fields in UIs.
Mint Flow (Issuer-Facing)
Issuer-level instructions call core logic with verifiers.
1pub fn mint_rwa_tokens(ctx: Context<MintRwaTokens>, amount: u64) -> Result<()> {
2 // Check Issuer Whitelist
3 require!(ctx.accounts.issuer.is_whitelisted, Error::Unauthorized);
4
5 // Title verification
6 let title_check = ctx.accounts.verifier.check_title_ownership()?;
7 require!(title_check.is_clean, Error::TitleLien);
8
9 let cpi_accounts = anchor_spl::token_2022::MintTo {
10 mint: ctx.accounts.mint.to_account_info(),
11 to: ctx.accounts.to.to_account_info(),
12 authority: ctx.accounts.mint_authority.to_account_info(),
13 };
14 let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
15 anchor_spl::token_2022::mint_to(cpi_ctx, amount)?;
16
17 // Post-mint: Embed metadata
18 if let Some(hook) = ctx.accounts.transfer_hook.key() {
19 // Custom RWA logic: filing verify
20 }
21
22 emit!(MintEvent { amount, to: ctx.accounts.to.key() });
23 Ok(())
24}
- Use CPI for safe minting.
- Override pre-mint to add compliance checks (title, whitelists) and revert early if verification fails.
- For illiquid or async-backed assets, combine mint with provisional issuance and oracle finalization to avoid over-minting.
Transfer Flow
Symmetric to mint, transfer invokes hook then updates accounts.
1pub fn execute_rwa_transfer(ctx: Context<ExecuteRwaTransfer>, amount: u64) -> Result<()> {
2 // Pre-hook: Variant-specific check
3 let variant = ctx.accounts.verifier.variant;
4 if variant == 1 { // Securitized
5 require!(!ctx.accounts.verifier.is_halted, Error::TradingHalted);
6 require!(ctx.accounts.to.is_whitelisted, Error::NotWhitelisted);
7 }
8
9 let cpi_accounts = anchor_spl::token_2022::Transfer {
10 from: ctx.accounts.from.to_account_info(),
11 to: ctx.accounts.to.to_account_info(),
12 authority: ctx.accounts.authority.to_account_info(),
13 };
14 let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
15 anchor_spl::token_2022::transfer(cpi_ctx, amount)?;
16
17 // Post-hook: Escrow if needed
18 if ctx.accounts.escrow.is_active {
19 // Hold portion
20 }
21
22 emit!(TransferEvent { amount, from: ctx.accounts.from.key(), to: ctx.accounts.to.key(), variant, title_verified: true });
23 Ok(())
24}
- Hook-first follows checks-effects-interactions and reduces reentrancy risk.
- For queued transfers, implement hook to check status and push into an escrow queue.
- Add transfer rate limits or liquidity buffers to defend against sudden runs.
Clawback Flow
Default clawbacks are issuer-gated; RWA overrides query reasons.
1pub fn clawback_transaction(ctx: Context<Clawback>, tx_sig: [u8; 64]) -> Result<()> {
2 // Issuer check
3 require!(ctx.accounts.issuer.is_whitelisted, Error::Unauthorized);
4
5 // Reverse via Token-2022 (if recent)
6 let reverse_amount = ctx.accounts.tx_log.get_amount(tx_sig)?;
7 let cpi_accounts = anchor_spl::token_2022::Transfer {
8 from: ctx.accounts.recipient.to_account_info(),
9 to: ctx.accounts.original_sender.to_account_info(),
10 authority: ctx.accounts.clawback_authority.to_account_info(),
11 };
12 let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
13 anchor_spl::token_2022::transfer(cpi_ctx, reverse_amount)?;
14
15 emit!(ClawbackEvent { tx_signature: tx_sig, reason: ctx.accounts.reason.clone() });
16 Ok(())
17}
- Reverse uses tx log for precision.
- Consider a time-bound policy for clawbacks.
Adding Trading Halts (Example: 30-day pause)
Halt handling keeps execution consistent.
1const HALT_DURATION: i64 = 30 * 24 * 60 * 60; // 30 days
2
3pub fn apply_halt(halt: &mut HaltState, condition: u8) -> Result<()> {
4 halt.is_active = true;
5 halt.start_time = Clock::get()?.unix_timestamp;
6 halt.end_time = halt.start_time + HALT_DURATION;
7 halt.condition = condition;
8 Ok(())
9}
- Keep halt accounting transparent: emit HaltEvent and track separately.
- For RWA products, halts may address regulatory events, document in metadata.

