Skip to main content

Contract Architecture

The RWT contract is the on-chain engine behind — a vault-backed token that aggregates yield from across the AREAL portfolio. The contract is deployed on Solana and leverages MagicBlock Ephemeral Rollups for real-time per-second yield accumulation.

On-Chain Accounts

All core state is stored in owned by the RWT program. This ensures trustless, permissionless access to vault operations.

EngineAuthority

Stores the top-level authority address that controls the entire RWT Engine contract. This authority can execute all governance-gated instructions and can be transferred to any address — another DAO, a multisig, or an individual account. Seeds: ["engine_authority"].

RwtVault

The main vault PDA. Stores the portfolio of Ownership Tokens, tracks total invested capital, total RWT supply, and current NAV Book Value. Seeds: ["rwt_vault"].

RwtMint

The mint authority PDA for the RWT SPL token. Only the vault program can mint new RWT through the mint_rwt instruction. Seeds: ["rwt_mint"].

CapitalAccumulator

Buffer account that holds deposited capital (USDC and other approved tokens) before it is deployed into Ownership Token positions. Receives funds from mint_rwt and OT sales. Strategy execution draws from this account. Seeds: ["capital_accumulator"].

VaultClaimAccount

The vault’s own ClaimAccount in the Yield Distribution contract. Receives per-second RWT yield from every OT held in the vault — just like any regular holder’s ClaimAccount. Seeds: ["claim", rwt_vault] (in the Yield Distribution program).

YieldAccumulator

Staging account for yield claimed from VaultClaimAccount. Holds yield before it is split by distribute_yield (70% book value, 15% liquidity, 5% treasury, 10% reserve). Delegated to MagicBlock ER. Seeds: ["yield_accumulator"].

DistributionConfig

Stores the yield distribution ratios (default 70/15/5/10) and destination account references. The DAO can update these ratios at any time via futarchy vote. Seeds: ["distribution_config"].

StrategyConfig

Stores the current strategy_authority, OT whitelist, and portfolio constraints (max trade size, concentration limits, diversification rules). Seeds: ["strategy_config"].

AcceptedMints

Registry of tokens approved by the DAO for RWT minting. Each entry maps a token mint to its MagicBlock oracle price feed for USD conversion. Seeds: ["accepted_mints"].

MintGuardians

List of guardian wallets authorized to pause/unpause RWT minting for the entire contract. Also stores the current mint_paused flag. Guardians are appointed by the DAO — any single guardian can trigger an emergency pause. Seeds: ["mint_guardians"].

Destination Accounts

Treasury

Receives 5% of distributed yield. Controlled by AREAL DAO.

Reserve Pool

Receives 10% of distributed yield. Safety buffer managed via Reserve Fund.

Liquidity Pool

Receives 15% of distributed yield. Deployed into RWT master pools on the native DEX.

Core Instructions

The RWT program exposes the following instructions that drive the vault lifecycle.

initialize_vault

Creates all core PDAs: EngineAuthority, RwtVault, RwtMint, CapitalAccumulator, YieldAccumulator, DistributionConfig, StrategyConfig, and AcceptedMints. Sets the initial engine authority, distribution ratios, and registers the initial accepted deposit mints with their oracle feeds.Authority: Governance multisig (one-time call)
Accounts:
  - authority:           Signer (governance)
  - rwt_vault:           PDA (init)
  - rwt_mint:            PDA (init)
  - yield_accumulator:   PDA (init)
  - distribution_config: PDA (init)
  - system_program
  - token_program
Mints RWT in exchange for any DAO-approved token. The entire operation is atomic within a single Solana block:
  1. Snapshot NAV — reads the current rwt_vault.nav_book_value (kept up-to-date by the per-second yield cycle in ER)
  2. Convert deposit to USD — reads oracle price feed for non-USD tokens
  3. Calculate RWT amountrwt_out = net_deposit_usd / nav_book_value
  4. Apply fee — 1% total (0.5% to Capital Accumulator, 0.5% to DAO)
  5. Transfer deposit to Capital Accumulator
  6. Mint RWT to user’s wallet
  7. Update NAV — atomically reflects the new deposit in total_invested_capital
All 7 steps execute in one transaction, one block. The user sends tokens and receives RWT at the exact NAV price — no slippage from NAV changes between steps.The contract checks the mint_paused flag in MintGuardians — if any guardian has triggered an emergency pause, all minting is halted globally until unpaused.Authority: Permissionless — anyone can call (unless globally paused)
Accounts:
  - user:                Signer
  - user_deposit_ata:    User's token account (any approved mint)
  - user_rwt_ata:        User's RWT token account
  - rwt_vault:           PDA (mut)
  - rwt_mint:            PDA (mut)
  - capital_accumulator: PDA (mut)
  - dao_fee_ata:         DAO fee destination
  - oracle_price_feed:   MagicBlock oracle account for deposit token / USD
  - accepted_mints:      PDA (approved mints registry)
  - mint_guardians:      PDA (global pause check)
  - token_program

Args:
  - amount: u64          Deposit amount in deposit token decimals
  - deposit_mint: Pubkey Mint of the deposit token
Emergency pause — halts all RWT minting globally. Any single guardian from the MintGuardians list can trigger this immediately, without a DAO vote. Designed for rapid response to exploits, oracle failures, or market emergencies.Authority: Any guardian from MintGuardians
Accounts:
  - guardian:            Signer (must be in MintGuardians list)
  - mint_guardians:      PDA (mut, sets mint_paused = true)
Resumes RWT minting after an emergency pause. Minting continues at the current NAV Book Value — the price is not frozen during the pause, it reflects the latest vault state at the moment of resumption. Only the Engine Authority (DAO) can unpause — ensuring that a single guardian cannot unilaterally resume minting without community consensus.Authority: Engine Authority (DAO governance)
Accounts:
  - engine_authority:    Signer (current engine authority)
  - mint_guardians:      PDA (mut, sets mint_paused = false)
Adds or removes guardian wallets from the MintGuardians list. The DAO votes (via futarchy) to appoint trusted individuals or entities who can trigger emergency mint pauses.Authority: Engine Authority (DAO governance)
Accounts:
  - engine_authority:    Signer (current engine authority)
  - mint_guardians:      PDA (mut)

Args:
  - wallet: Pubkey       Guardian wallet address
  - action: enum         { Add, Remove }
Adds or removes tokens from the list of accepted deposit mints for mint_rwt. Each approved token must have a corresponding MagicBlock oracle price feed. The DAO community votes (via futarchy) to approve new deposit tokens or revoke existing ones.Authority: DAO governance (futarchy vote)
Accounts:
  - governance:          Signer (DAO governance)
  - accepted_mints:      PDA (mut)

Args:
  - mint: Pubkey         Token mint to add/remove
  - oracle_feed: Pubkey  MagicBlock oracle price feed for this token
  - action: enum         { Add, Remove }
Claims accumulated RWT rewards from the vault’s ClaimAccount (in the Yield Distribution contract) and moves them into the YieldAccumulator. The RWT Vault has its own ClaimAccount — just like any OT holder — and receives per-second yield from every OT it holds.Runs every second inside the Ephemeral Rollup as part of the atomic yield cycle.Authority: Permissionless (crank)
Accounts:
  - crank:               Signer
  - rwt_vault:           PDA
  - yield_accumulator:   PDA (mut)
  - vault_claim_account: Vault's ClaimAccount in Yield Distribution (mut)
  - yield_distribution:  Yield Distribution program (CPI)
  - token_program
Reads the accumulated yield from YieldAccumulator and splits it according to DistributionConfig ratios: 70% credited to vault book value, 15% to liquidity, 5% to treasury, 10% to reserve.Authority: Permissionless (crank)
Accounts:
  - crank:               Signer
  - yield_accumulator:   PDA (mut)
  - distribution_config: PDA
  - rwt_vault:           PDA (mut)
  - treasury_ata:        Treasury destination
  - reserve_ata:         Reserve destination
  - liquidity_ata:       Liquidity pool destination
  - token_program
Updates the yield distribution ratios and/or destination accounts in DistributionConfig. The DAO community can vote (via futarchy) to change how yield is split — adjusting percentages, adding new destinations, or redirecting flows at any time. All ratios must sum to 100%.Authority: DAO governance (futarchy vote)
Accounts:
  - governance:          Signer (DAO governance)
  - distribution_config: PDA (mut)

Args:
  - book_value_bps: u16      Book value allocation (basis points)
  - liquidity_bps: u16       Liquidity pool allocation (basis points)
  - treasury_bps: u16        Treasury allocation (basis points)
  - reserve_bps: u16         Reserve pool allocation (basis points)
Recalculates the NAV Book Value based on the current total invested capital (including accumulated book value credits) and the total RWT supply. Updates the rwt_vault.nav_book_value field.Authority: Permissionless (crank)
Accounts:
  - crank:               Signer
  - rwt_vault:           PDA (mut)
Draws capital from the Capital Accumulator and executes a buy order for a specific Ownership Token on the AREAL native DEX. The vault routes the swap through the DEX. Only callable by the current strategy_authority.Authority: strategy_authority (governance or AI agent)
Accounts:
  - strategy_authority:  Signer (current strategy operator)
  - rwt_vault:           PDA (mut)
  - capital_accumulator: PDA (mut, source of capital)
  - strategy_config:     PDA
  - vault_ot_ata:        Vault's OT destination account (mut)
  - dex_pool:            RWT/OT pool on native DEX
  - dex_program
  - token_program

Args:
  - ot_mint: Pubkey      Target Ownership Token mint
  - amount: u64          Capital to deploy (in deposit token decimals)
  - min_ot_out: u64      Minimum OT to receive (slippage protection)
Sells a specific Ownership Token on the AREAL native DEX and returns the proceeds to the Capital Accumulator. The capital remains in the accumulator until redeployed by the strategy authority. Only callable by the current strategy_authority.Authority: strategy_authority (governance or AI agent)
Accounts:
  - strategy_authority:  Signer (current strategy operator)
  - rwt_vault:           PDA (mut)
  - capital_accumulator: PDA (mut, receives proceeds)
  - strategy_config:     PDA
  - vault_ot_ata:        Vault's OT source account (mut)
  - dex_pool:            RWT/OT pool on native DEX
  - dex_program
  - token_program

Args:
  - ot_mint: Pubkey      Target Ownership Token mint
  - ot_amount: u64       Amount of OT to sell
  - min_capital_out: u64 Minimum capital to receive (slippage protection)
Transfers the strategy_authority role to any address at any time. The DAO community can vote (via futarchy) to reassign portfolio management to a new operator — whether that’s an AI agent, a different multisig, an individual wallet, or back to the DAO itself. There are no restrictions on who can become the new authority or when the transfer can occur.Authority: DAO governance (futarchy vote)
Accounts:
  - governance:          Signer (governance multisig)
  - strategy_config:     PDA (mut)

Args:
  - new_authority: Pubkey   New strategy operator address
Transfers the top-level Engine Authority of the entire RWT contract to a new address. The new authority gains full control over all governance-gated instructions: update_distribution_config, update_accepted_mints, set_strategy_authority, update_strategy_config, and transfer_engine_authority itself.This enables the RWT Engine to be handed over to another DAO, a different multisig, a single account, or any on-chain governance structure. The transfer takes effect immediately — no timelock or multi-step confirmation.Authority: Current Engine Authority only
Accounts:
  - current_authority:   Signer (current engine authority)
  - engine_authority:    PDA (mut)

Args:
  - new_authority: Pubkey   Address of the new engine authority

Engine Authority

The RWT Engine contract has a single top-level authority stored in the EngineAuthority PDA. This is the root of trust for the entire contract — it controls all governance-gated operations. The engine authority can be transferred to any address at any time — enabling the following scenarios:

DAO-to-DAO transfer

The current DAO transfers control of the RWT Engine to another DAO with different governance structure, jurisdiction, or community.

Multisig migration

Authority moves from one multisig to another — for example, when the security council rotates members or upgrades to a different multisig implementation.

Progressive decentralization

Start with a founding team multisig, transition to a community DAO, then to a fully autonomous on-chain governance contract.

Emergency takeover

In case of governance failure, the community can vote to transfer authority to a trusted entity or security council for temporary crisis management.
transfer_engine_authority is irreversible from the perspective of the old authority — once transferred, the previous authority has no special access. The new authority must explicitly transfer back if reversal is needed. This is by design: the RWT Engine is a sovereign contract that can be fully owned by whoever holds the authority.

Portfolio Management

The RWT Vault actively manages a portfolio of Ownership Tokens — buying and selling them exclusively on AREAL’s native DEX. This design ensures all trades are transparent, on-chain, and constrained to the protocol’s own liquidity infrastructure.

Capital Accumulator

The Capital Accumulator is the buffer between user deposits and OT positions. Capital never moves directly from a mint into Ownership Tokens — it always passes through the accumulator first. Inflows — capital enters the accumulator from:
  • mint_rwt — user deposit (net amount after DAO fee)
  • mint_rwt — 0.5% vault fee from every mint
  • vault_sell_ot — proceeds from selling Ownership Tokens
  • distribute_yield — 70% of OT yield credited as book value growth
Outflows — capital leaves the accumulator only via:
  • vault_buy_ot — purchasing Ownership Tokens on the native DEX
The Capital Accumulator balance is always included in total_invested_capital for NAV Book Value calculation. Whether capital sits as USDC in the accumulator or has been deployed into OT positions — it all backs RWT. Undeployed capital simply hasn’t been converted into OT positions yet, but it still counts toward NAV.

Execution Strategies

Capital in the accumulator is deployed into OT positions according to an execution strategy defined by the strategy authority. The contract does not execute a single large buy — instead, it supports gradual deployment patterns to minimize market impact and optimize entry prices.

DCA (Dollar-Cost Averaging)

Splits the total capital into equal portions and executes buys over a defined period (e.g., deploy 100KintoOTAover60days= 100K into OT-A over 60 days = ~1,667/day). Reduces timing risk and smooths entry price.

Target Allocation

Defines target portfolio weights per OT (e.g., 30% OT-A, 25% OT-B, 20% OT-C). The strategy authority executes trades to converge toward these targets as capital enters the accumulator.

Opportunistic

The strategy authority (especially an AI agent) deploys capital when market conditions are favorable — buying dips, reacting to yield changes, or capitalizing on liquidity events.
Execution strategies are not hardcoded in the contract. The contract provides the primitives (vault_buy_ot, vault_sell_ot) and the constraints (StrategyConfig). The strategy logic lives in the strategy authority — whether that’s a DAO proposal, a multisig workflow, or an AI agent’s decision engine.

Strategy Authority

Portfolio operations (vault_buy_ot, vault_sell_ot) are gated by a dedicated strategy_authority — a role stored in the StrategyConfig PDA. This role is separate from the governance multisig and can be reassigned via set_strategy_authority.

Phase 1: Governance-driven

Initially, strategy_authority is held by the DAO. Buy/sell decisions are proposed and voted on through futarchy before execution.

Phase 2: AI Agent

Governance transfers strategy_authority to an autonomous AI agent. The agent executes portfolio strategies within on-chain constraints — no off-chain trust required.

StrategyConfig Account

The StrategyConfig PDA stores parameters that constrain portfolio operations, regardless of who holds the strategy_authority:
ParameterDescription
strategy_authorityCurrent address authorized to execute buy/sell
allowed_ot_mintsWhitelist of OT mints approved by governance
max_single_trade_bpsMax trade size as basis points of total vault capital (e.g., 500 = 5%)
max_daily_volume_bpsMax daily trading volume as bps of vault capital
min_diversificationMinimum number of distinct OTs the vault must hold
max_concentration_bpsMax allocation to a single OT as bps of total portfolio
These constraints are enforced on-chain by the program logic. Even an AI agent with full strategy_authority cannot exceed these limits — the transaction will simply fail. Governance can update these parameters via update_strategy_config.

Trade Execution Flow

1

Strategy decision

The strategy authority (governance or AI agent) decides to buy or sell a specific OT based on yield performance, diversification targets, or market conditions.
2

Constraint validation

The contract checks the trade against StrategyConfig limits: is the OT whitelisted? Does the trade size exceed max_single_trade_bps? Would it violate max_concentration_bps or min_diversification?
3

Capital flow

For buys: capital is drawn from the Capital Accumulator → swapped on native DEX → OT deposited into vault positions. For sells: OT is sold on native DEX → proceeds returned to the Capital Accumulator.
4

Vault state update

After the trade, rwt_vault portfolio balances and total_invested_capital are updated atomically. A subsequent update_nav reflects the new portfolio composition in NAV Book Value.
All trades execute exclusively on the AREAL native DEX. The contract has no CPI calls to external DEX programs — this eliminates external dependency risk and ensures all liquidity flows strengthen the protocol’s own markets.

Yield Flow

The RWT Vault receives yield from Ownership Tokens through the Yield Distribution contract. The vault has its own ClaimAccount — just like any OT holder — and receives per-second RWT rewards from every OT it holds.

OT yield accrual

The RWT Vault holds OTs across multiple projects. Each OT project distributes yield via the Yield Distribution contract, crediting RWT rewards to the vault’s ClaimAccount every second — just like any regular holder.

Yield collection

The accumulate_yield instruction claims accumulated RWT from the vault’s ClaimAccount and moves it into the YieldAccumulator. In the Ephemeral Rollup, this happens every second — keeping yield data real-time.

Distribution split

The distribute_yield instruction reads DistributionConfig and splits accumulated yield:
  • 70% → credited to rwt_vault.total_invested_capital (grows NAV Book Value)
  • 15% → transferred to liquidity pool destination
  • 5% → transferred to AREAL Treasury
  • 10% → transferred to Reserve Pool

NAV update (atomic)

update_nav recalculates NAV Book Value using the updated total_invested_capital. In the Ephemeral Rollup, this runs every second immediately after distribute_yield — ensuring NAV always reflects the latest yield.
The sequence accumulate_yielddistribute_yieldupdate_nav runs as an atomic per-second cycle inside the MagicBlock Ephemeral Rollup. NAV Book Value is always current — there is no lag between yield accrual and price update.

The on-chain NAV Book Value is a deterministic calculation stored in the RwtVault account, updated every second by the yield cycle in the Ephemeral Rollup:
NAV Book Value = total_invested_capital / total_rwt_supply
Where total_invested_capital is the sum of all capital backing RWT, from three sources:
SourceWhat it isHow it enters
Capital Accumulator (USDC)User deposits from mint_rwt + 0.5% vault fee from mintingEvery mint adds to CA balance
OT Portfolio (valued in USD)Ownership Tokens purchased by the strategy authorityvault_buy_ot moves capital from CA → OT positions
Yield credits (70%)70% of yield from OT distributions, credited to book valuePer-second via accumulate_yielddistribute_yield
And total_rwt_supply = current circulating supply of the RWT mint.
The Capital Accumulator balance (undeployed USDC) is always counted in total_invested_capital. Whether capital sits in the accumulator or has been deployed into OT positions — it all backs RWT and is reflected in NAV.
NAV grows continuously because:
  • Every second: OT yield flows through accumulate_yielddistribute_yield → 70% credited to total_invested_capitalupdate_nav
  • On every mint: deposit + vault fee added to Capital Accumulator → total_invested_capital updated atomically
All arithmetic uses fixed-point u128 operations with 12 decimal places of precision to avoid floating-point drift. The NAV is stored as a u64 value in USDC-equivalent lamports (6 decimals).

Mint price derivation (atomic, single block)

The mint price is always expressed in USD. The entire calculation and execution happen atomically in one Solana block — the user cannot be front-run or receive a stale price:
// Step 1: Snapshot current NAV (updated every second by ER yield cycle)
nav_book_value = rwt_vault.nav_book_value

// Step 2: Convert deposit to USD (oracle for non-USD tokens)
token_usd_price = oracle_price_feed.price    // e.g., SOL = $145.32
deposit_usd_value = deposit_amount * token_usd_price

// Step 3: Apply fee
fee_usd = deposit_usd_value * 0.01
vault_fee = fee_usd / 2    → transferred to Capital Accumulator
dao_fee = fee_usd / 2      → transferred to DAO

// Step 4: Calculate RWT amount at exact NAV
net_usd = deposit_usd_value - fee_usd
rwt_amount = net_usd / nav_book_value

// Step 5: Mint + update NAV atomically
mint(rwt_amount) → user
capital_accumulator += net_usd + vault_fee
total_invested_capital += net_usd + vault_fee  // CA balance is part of total
total_rwt_supply += rwt_amount
nav_book_value = total_invested_capital / total_rwt_supply
For USDC and other USD-pegged stablecoins, the oracle price is effectively $1.00, so the conversion is 1:1. For volatile tokens (e.g., SOL, wBTC), the oracle provides a real-time USD price from MagicBlock’s Ephemeral Rollup, ensuring accurate pricing at the moment of mint.
The NAV update at the end of mint is part of the same transaction. This means the next user who mints will see the updated NAV that includes the previous user’s deposit — zero dilution, zero stale pricing.

MagicBlock Integration

The RWT contract uses for two critical functions: per-second yield accumulation and real-time oracle price feeds.

Yield accumulation

The YieldAccumulator account is delegated to the Ephemeral Rollup. This allows the crank to call accumulate_yield every second with sub-millisecond finality inside the rollup.

Oracle price feeds

MagicBlock provides real-time USD price feeds for all accepted deposit tokens. The mint_rwt instruction reads these oracle accounts to convert any approved token into its USD equivalent at the moment of mint.

L1 commits

Periodically (configurable, default every 60 seconds), the accumulated state is committed back to Solana L1. This ensures L1 reflects an up-to-date yield balance for distribution.

Lifecycle

1

Delegate

The YieldAccumulator PDA is delegated to MagicBlock via the delegation program. The account becomes writable in the Ephemeral Rollup while remaining readable on L1.
2

Accumulate in ER

The crank service calls accumulate_yield every second inside the Ephemeral Rollup. Each call reads OT yield sources and increments the accumulator balance.
3

Commit to L1

On a periodic basis, the rollup commits the YieldAccumulator state back to Solana L1. After commit, distribute_yield can be called on L1 to split and transfer funds.
4

Crank automation

A permissionless crank calls distribute_yield after each L1 commit. Anyone can run the crank — no special authority required.
Delegating only the YieldAccumulator (not the entire vault) minimizes the trust surface. The vault’s core state — balances, NAV, mint authority — remains on Solana L1 at all times.

Security Considerations

Authority model

The EngineAuthority is the root of trust — controls all governance-gated instructions and can be transferred to any address via transfer_engine_authority. Portfolio operations require strategy_authority. All other instructions are permissionless.

PDA ownership

All vault accounts are PDAs owned by the program. No external wallet can modify vault state directly. Mint authority is held exclusively by the RwtMint PDA.

Overflow protection

All arithmetic uses checked math (checked_add, checked_mul, checked_div). Fixed-point u128 operations prevent precision loss. Transactions revert on overflow.

Reentrancy safety

Solana’s runtime model prevents reentrancy by design. Account locks ensure no concurrent modification of vault state within the same slot.

Strategy constraints

Portfolio operations are bounded by on-chain limits: OT whitelist, max trade size, concentration caps, diversification minimums. Even an autonomous agent cannot exceed these parameters.

DEX-only execution

All buy/sell operations route exclusively through the AREAL native DEX via CPI. No external DEX integrations — eliminating third-party dependency and exploit surface.
The RWT contract is currently in development. This documentation describes the target architecture. Contract code has not yet been audited. Do not rely on these specifications for production use until a formal audit is completed.