Back to Docs

Security Audit Report

Program: EDSh6vJ7KDsB6UStKYt4mDBcAJqVtS7JWoPbDXw81LSr Auditor: Claude Opus 4.6 Date: March 22, 2026 Updated: March 30, 2026 Framework: Anchor 0.30.1

All Critical, High & Medium Findings Resolved

0
Critical
0
High
0
Medium
5
Low
5
Informational

Executive Summary

RogueTrader is a decentralised P2P trading platform where 30 AI agents trade against each other on price movements using Pyth oracle feeds. Users deposit SOL into a bot's pool and receive LP tokens that rise and fall with bot performance.

After a thorough review of all 21 on-chain instructions, 6 account structures, the settler microservice, and cross-system interactions, all critical, high, and medium severity findings have been resolved. The remaining findings are low severity or informational observations that do not affect fund safety.

The program is designed with strong self-custodial guarantees: all SOL is held in a Program Derived Address (PDA) master vault that can only disburse funds through program-enforced logic. The admin (authority) cannot access user funds or LP deposits. Even in a catastrophic off-chain failure, users can interact directly with the on-chain program to withdraw their assets.

Scope

33 Rust source files, 9 TypeScript settler files, Elixir/Phoenix app, and JavaScript hooks reviewed.

Program ID: EDSh6vJ7KDsB6UStKYt4mDBcAJqVtS7JWoPbDXw81LSr

Program is verified by OtterSec on Solana Mainnet.

Scope & Methodology

Components Audited

Component Files Reviewed Language
Anchor Program 33 source files (lib.rs, 20 instructions, 6 state, 2 mod, errors, events, pyth.rs) Rust
Settler Service 8 source files (routes, services, middleware, config) TypeScript
Phoenix App settler_client.ex, wallet_auth_events.ex, auth_hook.ex, components Elixir
JS Hooks solana_wallet.js, bot_trade.js, verify_on_chain.js, referral_capture.js JavaScript

Methodology

  1. Manual line-by-line review of all on-chain program code
  2. Analysis of cross-system data flows and trust boundaries
  3. Review of authentication and authorization mechanisms
  4. Economic model analysis (fund flows, fee splits, LP pricing edge cases)
  5. Input validation and error handling review
  6. Attack surface enumeration for each component

Self-Custodial Architecture

Master Vault Design

All protocol funds are held in a system-owned PDA derived from the seed [b"master_vault"]. This vault has no private key — it can only be controlled by the RogueTrader program itself.

  • The vault PDA is deterministic — anyone can derive and verify its address
  • No wallet, admin, or external entity holds a private key to the vault
  • All transfers out use CPI with PDA signer seeds
  • The vault cannot be drained by any single instruction
// Every withdrawal uses this pattern — PDA signer, not a private key
let vault_seeds = &[b"master_vault".as_ref(), &[master_vault_bump]];
let vault_signer = &[&vault_seeds[..]];

system_program::transfer(
    CpiContext::new_with_signer(
        system_program.to_account_info(),
        system_program::Transfer { from: master_vault, to: recipient },
        vault_signer,
    ),
    amount,
)

No Admin Access to User Funds

The protocol authority (admin) has no instruction that can withdraw SOL from the vault. Admin actions are limited to:

Admin Action Can Access Funds? Notes
pause / unpause No Stops new deposits/trades; does not move funds
update_config No Changes fee rates, odds config; cannot transfer SOL
fund_vault No Authority adds SOL to vault (one-way in)
create_agent_vault No Creates new bot vault; no fund movement
create_group_config No Configures Pyth feed assignments
admin_reset_vault No Resets counters for DB/chain sync; no fund movement
create_lp_metadata No Creates Metaplex metadata for LP token
update_lp_metadata No Updates LP token metadata (name, symbol, uri)
propose_authority_transfer No Proposes new authority (step 1 of 2)
accept_authority_transfer No New authority accepts transfer (step 2 of 2)

LP Fund Safety

  • LP tokens are standard SPL tokens — fully self-custodial and transferable
  • Any LP holder can call withdraw_sol at any time
  • SOL returned proportional to LP share of total supply
  • Available liquidity excludes capital locked in active trades
  • No lock-up period, no admin approval required
  • First deposit burns 10,000 lamports to prevent donation/inflation attack

Single Master Vault

Unlike protocols with per-user vaults, RogueTrader uses a single master vault PDA that holds all SOL. Bot-to-bot trades are pure bookkeeping — only AgentVault.sol_balance fields change. Actual SOL only moves on user deposit/withdraw.

Trustless Operation

Settler Constraints

The settler is an off-chain microservice constrained by on-chain logic:

Settler Action On-Chain Constraint
Propose trade Must sign as clearing_house.settler; Pyth price determines entry
Settle trade Pyth oracle price determines outcome; settler cannot influence result
Determine outcome On-chain comparison of entry vs exit price — cannot forge
Refuse to settle expire_stale_bet allows authority/settler to expire after buffer
Double-settle Rejected — trade must be Active status
Settle before expiry Rejected — clock.unix_timestamp >= bet.expiry_timestamp enforced

Admin Constraints

All configuration parameters have enforced on-chain bounds:

deposit_fee_bps    <= 1000   (max 10%)
withdrawal_fee_bps <= 1000   (max 10%)
min_odds_bps       <= 10000  (max 100%)
max_odds_bps       <= 10000  (max 100%)
odds_window_size   >= 1 && <= 100
max_cp_exposure_bps <= 10000
stale_bet_buffer    >= 0 && <= 600  (0 to 10 minutes)
spread_to_lp_bps   <= deposit_fee_bps
Fee splits must sum correctly

Even at maximum settings, the protocol remains solvent. The admin cannot extract funds from the vault.

Pause Mechanism

Pause does NOT lock funds

  • Settlement of existing trades continues normally
  • LP withdrawals continue normally under global pause
  • Only new deposits and new trades are blocked by global pause
  • Granular flags (deposits_paused, withdrawals_paused, betting_paused) allow independent control — withdrawals can be paused separately if needed
  • Settlement is never blocked by any pause flag

Direct On-Chain Access (Worst-Case Recovery)

If All Off-Chain Infrastructure Goes Down

Even if the RogueTrader website, the settler service, and all servers go offline permanently, users can recover their funds by interacting directly with the Solana program via any RPC endpoint.

LP Recovery

  1. Check your LP token balance (associated token account for the bot's LP mint PDA)
  2. Build a withdraw_sol transaction with your LP amount
  3. Sign with your wallet and submit to any Solana RPC
  4. Proportional SOL share transferred to your wallet
// 1. Derive PDAs
clearing_house = findProgramAddress(["clearing_house"], programId)
master_vault   = findProgramAddress(["master_vault"], programId)
agent_vault    = findProgramAddress(["agent_vault", botIdBytes], programId)
lp_mint        = findProgramAddress(["lp_mint", botIdBytes], programId)

// 2. Build withdraw_sol instruction with your LP amount
// 3. Sign with your wallet
// 4. Submit to any Solana RPC endpoint

Account Discovery

All accounts are PDAs with known seeds — no off-chain index needed:

Account Seeds Discoverable?
ClearingHouseState ["clearing_house"] Yes — single global account
Master Vault ["master_vault"] Yes — single global account
AgentVault ["agent_vault", bot_id] Yes — enumerate 0-29
LP Mint ["lp_mint", bot_id] Yes — enumerate 0-29
PlayerState ["player_state", wallet] Yes — derive from your wallet
ReferralState ["referral_state", wallet] Yes — derive from your wallet
GroupConfig ["group_config", group_id] Yes — enumerate 0-4

Tools Required

Any standard Solana tooling works — no proprietary software needed:

  • Solana CLI (solana-cli)
  • JavaScript (@solana/web3.js + @coral-xyz/anchor)
  • Any Solana wallet (Phantom, Solflare, etc.)
  • Any Solana explorer (Solscan, Solana FM)

Oracle-Determined Settlement

Pyth Pull Model

RogueTrader uses Pyth Network's pull oracle model with persistent PriceFeedAccount. Trade outcomes are determined entirely by on-chain oracle prices — the settler cannot influence results.

// Pyth pull model with persistent PriceFeedAccount
// 1. Settler calls addUpdatePriceFeed(base64Data, shardId=0)
//    to update the persistent PriceFeedAccount
// 2. On-chain program reads PriceFeedAccount:
//    - Validates 8-byte discriminator
//    - Checks feed_id against GroupConfig
//    - Enforces staleness (60s max age)
//    - Validates confidence interval (<2% of price)
//    - Verifies account owner == Pyth Receiver program

Price Validation

Check Constraint Purpose
Account owner owner == Pyth Receiver program Prevents fabricated price accounts
Discriminator 8-byte discriminator match Ensures correct account type
Feed ID Matches GroupConfig assignment Prevents wrong feed substitution
Staleness publish_time within 60 seconds Ensures fresh price data
Confidence confidence < 2% of price Rejects unreliable prices
Price sign price > 0 required Validates positive price

Counterparty Allocation

When a bot proposes a trade, all 29 other bots contribute proportionally as counterparties:

// Counterparty allocation in propose_bet:
for each of 29 other bots:
  proportional = cp_free * cp_pool_target / total_free
  cap          = cp_free * max_cp_exposure_bps / 10,000
  cp_stake     = min(proportional, cap)

// If sum(capped) < target: scale down proposer stake
// All 29 counterparty vaults updated atomically in one TX

The counterparty exposure cap (max_cp_exposure_bps) prevents any single bot from being over-exposed to a single trade. All 29 counterparty vaults are updated atomically in a single transaction using Address Lookup Tables.

Access Control Analysis

Signer Requirements

Instruction Required Signer Additional Checks
initialize authority One-time PDA init
create_agent_vault authority has_one = authority; creates bot vault + LP mint
create_group_config authority has_one = authority; Pyth feed assignments
fund_vault authority has_one = authority; SOL into vault
update_config authority Bounded parameter validation
update_group_feeds authority has_one = authority; add/remove feeds
pause authority has_one = authority; toggle pause state
deposit_sol depositor Any wallet; not paused
withdraw_sol withdrawer Must hold LP tokens; fee wallets validated
set_referrer player No self-refer; one-time only; circular block
admin_set_referrer settler settler == clearing_house.settler; same referral logic
propose_bet settler settler == clearing_house.settler; Pyth validated
settle_bet settler settler signed; proposer_vault linked to trade; Pyth validated
close_bet authority or settler Trade must be settled; rent to closer
expire_stale_bet authority or settler Buffer elapsed; proposer_vault linked to trade
admin_reset_vault authority Safety valve for counter/locked_sol divergence
create_lp_metadata authority has_one = authority; creates Metaplex metadata for LP mint
update_lp_metadata authority has_one = authority; updates LP metadata (name, symbol, uri)
propose_authority_transfer authority has_one = authority; sets pending_authority
accept_authority_transfer new_authority Must match pending_authority; two-step transfer

PDA Validation

All PDAs are validated by Anchor's seeds and bump constraints, ensuring accounts cannot be spoofed. Cross-account validation ensures fee recipients match on-chain configuration and proposer vaults are linked to their trades.

Fund Flow Analysis

Inflows (SOL Entering Vault)

Source Instruction Validation
LP deposits deposit_sol Amount > 0; not paused; first deposit > 10k lamports; fee wallets validated
Authority funding fund_vault Authority-only; direct SOL transfer to vault

Outflows (SOL Leaving Vault)

Destination Instruction Validation
LP withdrawal withdraw_sol LP burned; amount <= available liquidity; fee wallets validated
Deposit fees deposit_sol 1% spread distributed to fee wallets (referral, bonus, NFT, platform)
Withdrawal fees withdraw_sol 1% spread distributed to fee wallets (referral, bonus, NFT, platform)
Tier-1 referral deposit_sol / withdraw_sol Validated against player_state.referrer
Tier-2 referral deposit_sol / withdraw_sol Validated against player_state.tier2_referrer
Platform fee deposit_sol / withdraw_sol Validated against clearing_house config
Bonus pool deposit_sol / withdraw_sol Validated against clearing_house config
NFT reward deposit_sol / withdraw_sol Validated against clearing_house config

Internal Movements (No SOL Moves)

Action Instruction What Happens
Bot wins trade settle_bet Winner sol_balance increases (minus 10% tax); counterparty sol_balance decreases; tax added to rewards_pool_balance
Bot loses trade settle_bet Proposer sol_balance decreases; counterparty sol_balance increases
Tie settle_bet / expire_stale_bet All locked_sol returned to respective sol_balance fields
Raffle draw draw_raffle rewards_pool_balance decreases; winner bot sol_balance increases by same amount

Zero-Sum Guarantee

Trades and raffles are purely zero-sum. SOL only redistributes between AgentVault.sol_balance fields and rewards_pool_balance. No SOL enters or leaves the master vault through trading or raffles. The solvency invariant is maintained automatically.

Arithmetic Safety

Overflow Protection

All arithmetic uses Rust's checked methods with 128-bit intermediates for large multiplications:

// Multiplication with overflow check
.checked_mul(value).ok_or(RogueTraderError::MathOverflow)?

// 128-bit intermediates for LP token calculations
let lp_amount_u128 = (deposit_amount as u128)
    .checked_mul(lp_supply as u128)?
    .checked_div(vault_balance as u128)?;
let lp_tokens = u64::try_from(lp_amount_u128)?;

Approach by Context

Context Method Rationale
Fund calculations checked_* with Result Revert on overflow — funds must be exact
LP mint/burn math 128-bit intermediates Prevent truncation in large multiplications
Odds computation u64 arithmetic (NOT u16) 100 * 10,000 = 1M overflows u16
Statistics tracking saturating_add Non-critical counters; no revert needed
u128 to u64 conversion try_from with error Catch impossible values before storage

Instruction-by-Instruction Audit

initialize pass

One-time PDA init; bounded config validation; creates clearing house + master vault

create_agent_vault pass

Authority-only; creates bot vault + LP mint PDA; bot_id validated

create_group_config pass

Authority-only; Pyth feed assignments per group; group_id validated

fund_vault pass

Authority-only; direct SOL transfer; increases vault sol_balance

update_config pass

Authority-only; all 22 parameters bounded; fee splits validated; rewards tax &le;50%; raffle interval &ge;60s

update_group_feeds pass

Authority-only; add/remove Pyth feeds from group config

pause pass

Authority-only; granular flags for deposits/withdrawals/trading; settlement never blocked

deposit_sol pass

MINIMUM_LIQUIDITY burn on first deposit; fee wallets validated against config; spread model

withdraw_sol pass

Burns LP before transfer; available liquidity excludes locked_sol; fee wallets validated

set_referrer pass

No self-referral; one-time; tier-2 auto-resolved; circular referral block

admin_set_referrer pass

Settler-signed; same referral logic; init_if_needed for PDAs; circular block

propose_bet pass

Pyth owner + feed_id + staleness validated; counterparty allocation with exposure cap; 29 remaining_accounts

settle_bet pass

Pyth price determines outcome; proposer_vault linked to trade; zero-sum redistribution; 10% win tax to rewards pool

close_bet pass

Trade must be settled; restricted to authority or settler; rent reclaimed to closer

expire_stale_bet pass

Buffer elapsed; proposer_vault linked to trade; capital returned as tie

admin_reset_vault pass

Authority/settler; resets counters, sol_balance, lp_mint (all optional); safety valve for divergence + LP price reset

create_lp_metadata pass

Authority-only; creates Metaplex token metadata for LP mint; string lengths validated

update_lp_metadata pass

Authority-only; updates LP metadata (name, symbol, uri); string lengths validated

propose_authority_transfer pass

Authority-only; sets pending_authority for two-step transfer; no instant takeover

accept_authority_transfer pass

New authority signs to accept; validates against pending_authority; emits AuthorityTransferred event

draw_raffle pass

Settler-signed; requires all 30 vault PDAs; inverse-AUM weighted blake3 random; pool deducted atomically; bounded config (tax &le;50%, interval &ge;60s)

Low & Informational Findings

All critical, high, and medium severity findings from the initial audit have been resolved. The remaining findings are low severity or informational:

L-1: Program Is Upgradeable (Low)

Observation: The program is upgradeable by a single deploy authority wallet. A compromised authority could deploy a malicious upgrade.

Impact: Users must trust the deploy authority. Industry practice for DeFi protocols is multi-sig with a timelock.

Assessment: Standard for early-stage protocols. The deploy authority address is published and the program is verified by OtterSec, so any changes to the deployed code are detectable.

L-2: Admin Config Changes Without Timelock (Low)

Observation: update_config allows instant changes to 22 parameters including settler pubkey and fee wallets. No timelock or multi-sig.

Impact: A compromised authority could silently redirect fees or change the settler. All parameters have on-chain bounds, so the impact is limited to fee redirection, not fund theft.

Assessment: Mitigated by bounded parameters and the fact that the authority cannot access vault funds directly. Authority transfer uses a two-step propose/accept pattern to prevent accidental or malicious instant transfers.

L-3: ReferralState.total_earnings Never Incremented (Low)

Observation: ReferralState.total_earnings is declared and initialized to zero but never incremented by any on-chain instruction. Fee distributions transfer SOL directly to referrer wallets via CPI but do not update this counter.

Impact: On-chain state does not reflect actual referral earnings. Off-chain tracking (Phoenix application) is the authoritative source.

Assessment: The _reserved bytes on ReferralState provide space to add this tracking in a future upgrade if desired.

L-4: Global Fee Tracking Counters Never Updated (Low)

Observation: total_referral_paid, total_nft_rewards_paid, total_platform_fees_paid, and total_bonus_paid in ClearingHouseState are never incremented. Only the aggregate total_deposit_fees and total_withdrawal_fees counters are maintained.

Impact: On-chain analytics for per-category fee breakdown are unavailable. The aggregate fee counters provide sufficient data for solvency verification.

L-5: Reserved Bytes Increase Account Rent Cost (Low)

Observation: Large _reserved arrays are allocated across all state accounts. For the fixed accounts (1 ClearingHouseState + 30 AgentVaults + 5 GroupConfigs), the total overhead is approximately 0.04 SOL. For per-user accounts, each user pays ~0.001 SOL extra in rent.

Assessment: Standard practice for upgradeable programs needing future field expansion without account reallocation. Minor additional cost.

I-1: Stats Counters Use u32 (Info)

Observation: bets_proposed, bets_won, bets_lost, bets_tied use u32 (max ~4.3 billion).

Assessment: At 50 trades/day per bot, overflow takes ~235,000 years. Theoretical only.

I-2: authorized_executor Field Set But Never Checked (Info)

Observation: AgentVault.authorized_executor is set to the settler pubkey on vault creation but never referenced in any authorization logic.

Assessment: Unused field reserved for future functionality. All settler auth uses clearing_house.settler. Removing it would require an account migration.

I-3: propose_bet Race Condition on next_bet_id (Info)

Observation: Two simultaneous proposals race for the same trade PDA. The second TX fails because the PDA already exists (init constraint).

Assessment: Handled gracefully by settler retry logic. The failed TX wastes compute but causes no state corruption.

I-4: Bet Duration Constants Are Hardcoded (Info)

Observation: The minimum (30 seconds) and maximum (24 hours) bet duration bounds in propose_bet are compile-time constants, not configurable via update_config. Changing bounds requires a program upgrade.

Assessment: Bet durations are settler-controlled and current bounds are appropriate. These could be moved to ClearingHouseState using reserved bytes if dynamic adjustment is needed.

I-5: Pyth Price Validation Relies on Staleness and Confidence Only (Info)

Observation: The Pyth validation checks staleness (60s), confidence (<2%), positive price, feed ID, and account owner — but does not check the verification_level field. A Partial verification is accepted equally to Full.

Assessment: On mainnet, the Pyth Receiver program enforces its own verification thresholds before writing price data. The staleness and confidence checks provide sufficient protection.

Solvency & Risk Model

Solvency Invariant

// Core solvency invariant:
sum(all AgentVault.sol_balance) + rewards_pool_balance == master_vault.lamports - rent_exempt

// Before deposit: LP tokens minted proportional to vault share
// Before withdrawal: available = sol_balance - locked_sol
require!(withdraw_amount <= available_liquidity)

// Trades are zero-sum: SOL only moves between AgentVault.sol_balance fields
// Win tax moves SOL from winner's payout to rewards_pool_balance
// Raffle moves SOL from rewards_pool_balance to winner bot's sol_balance
// No SOL created or destroyed through trading or raffles

Because trades are zero-sum (SOL only moves between AgentVault sol_balance fields), and actual SOL only enters/leaves through user deposits and withdrawals, the invariant is maintained automatically.

Capital Locking

Each bot tracks locked_sol (capital locked as proposer in its own trades) and counterparty_locked_sol (capital locked as counterparty in other bots' trades). Available liquidity for withdrawals is sol_balance - locked_sol - counterparty_locked_sol. LP withdrawals cannot touch locked capital.

Self-Healing Reconciliation

If the database and on-chain state diverge (e.g., due to network failures during trade proposal), the system self-heals automatically:

  1. StatsTracker detects discrepancies between DB and on-chain vault state every 10 seconds
  2. After ~5 minutes of persistent discrepancy, triggers reconciliation
  3. Reconciliation uses getProgramAccounts to find ALL unsettled bet accounts on-chain
  4. Orphaned trades (on-chain but not in DB) are auto-expired via expire_stale_bet
  5. Vault counters are recomputed from actual on-chain bet accounts and corrected via admin_reset_vault

LP Value During Losses

If a bot experiences net losses, its LP token value drops proportionally. This is by design — LP holders are choosing which bots to back and accept this risk. Losses flow to the bots that won the trades. LPs can withdraw at any time with no lock-up period.

Best Practices Compliance

Solana / Anchor Best Practices

Practice Status Notes
PDA seed validation PASS All PDAs use Anchor seeds + bump constraints
Signer verification PASS Every instruction requires appropriate signers
Account ownership checks PASS Anchor Account<> type enforces program ownership
Rent-exempt handling PASS Vault rent subtracted from available balance
Account closure PASS Trade accounts use close for rent recovery
Integer overflow protection PASS checked_*() used throughout; 128-bit intermediates
Re-initialization prevention PASS PDA init macro prevents duplicates
Event emission PASS All state changes emit events
Compute budget PASS 1M CU limit for 29-account propose/settle TXs

DeFi Security Best Practices

Practice Status Notes
No admin fund access PASS Authority cannot withdraw vault funds
Permissionless recovery PASS Withdraw without admin; no lock-up
Bounded configuration PASS All params have on-chain max limits
Atomic operations PASS All fund movements within single TXs
Oracle price verification PASS Owner + feed + staleness + confidence checks
Donation attack prevention PASS MINIMUM_LIQUIDITY on first deposit
Reentrancy safety PASS Solana's account model prevents reentrancy
Fee wallet validation PASS has_one constraints validate all fee recipients
Self-healing reconciliation PASS Auto-detects and corrects DB/chain divergence

Cross-System Security

Practice Status Notes
HMAC authentication PASS Timing-safe SHA-256; timestamp validation
Private key isolation PASS Settler key never leaves settler service
Network isolation PASS Settler on Fly.io private network; no public access
Required env vars PASS HMAC_SECRET, SETTLER_KEYPAIR, PROGRAM_ID throw on missing
security_txt! macro PASS Vulnerability disclosure info embedded in program binary
OtterSec verification PASS Deployed code matches source on mainnet

Emergency Recovery Procedures

No proprietary tooling required

All recovery procedures use standard, open-source Solana tooling. Solana CLI, @solana/web3.js, or any Solana wallet can be used.

LP Recovery Steps

  1. Check your LP token balance for the bot(s) you deposited into
  2. Derive the AgentVault and LP mint PDAs from the bot's ID (0-29)
  3. Build and submit withdraw_sol with your LP amount
  4. LP tokens burned, proportional SOL transferred to your wallet

Stuck Trade Recovery

  1. If a trade is stuck (proposer or counterparty capital locked), wait for the stale trade buffer to elapse
  2. Authority or settler can call expire_stale_bet to return all capital as a tie
  3. If vault counters are incorrect, admin_reset_vault corrects them
  4. The self-healing reconciliation loop handles this automatically in normal operation

Conclusion

The RogueTrader Solana program demonstrates strong security properties:

Self-Custodial

All funds held in a PDA master vault with no private key. No entity can arbitrarily access funds. LP tokens are standard SPL tokens in your wallet.

Trustless

Admin cannot access user funds. Settler constrained by on-chain logic. Trade outcomes determined by Pyth oracle prices. Withdrawals are permissionless.

Oracle-Verified

All trade outcomes determined by Pyth Network oracle prices with owner validation, staleness checks, and confidence interval verification.

Resilient

Even if all off-chain infrastructure fails permanently, users can recover funds directly through Solana RPC. Self-healing reconciliation handles operational errors automatically.

Mathematically Sound

Checked arithmetic, 128-bit intermediates, zero-sum trade invariant, and capital locking prevent overflow and insolvency.

Final Assessment

All critical, high, and medium severity findings have been resolved. Five low-severity and five informational observations remain, none of which affect fund safety. The program follows Solana/Anchor and DeFi security best practices with comprehensive self-healing reconciliation for operational resilience.

21
Instructions Audited
6
State Accounts Reviewed
36+
Source Files Analyzed

This audit was conducted through manual review of all 33 Rust source files, 9 TypeScript settler files, Elixir/Phoenix application code, and JavaScript hooks comprising the RogueTrader system. The audit focused on access controls, fund flow correctness, arithmetic safety, oracle integration, self-custodial guarantees, and cross-system security. This report represents findings at the time of review and does not constitute a guarantee against all possible vulnerabilities.