01
Bundle
Engine code, maps, sprites, and metadata compile into one deterministic ROM image.
/boot/solana/pda-rom
Arvex stores engine code, maps, sprites, and save-proof metadata inside Solana accounts. PDA chunks stay rent-exempt, while SHA-256 Merkle roots prove the bytes before the canvas ever boots.
PDA chunks
18
Merkle root
locked
RPC read
parallel
Pull it off the chain
Nothing here is cached and nothing is served from this page. Every byte below arrives from an RPC node and is checked before it is run.
DEPTH // PDA MAZE
1st-person raycaster stored as sealed account chunks.
Collect 3 ROM shards and reach the amber exit. WASD move/strafe · arrows turn · click for mouse-look
> terminal ready: select ROM and pull account chunks
Canvas accepts keyboard, mouse, click-to-boot, and fullscreen input.
Chunks
18 PDA chunks
Bytes on chain
184,320
Accounts read
0
Merkle root
7vMkK9...9VrP
The chain checks its own copy
A Solana program can verify account state with SHA-256 syscalls and zero-copy Merkle paths. The browser gets speed, while the program keeps a strict checksum trail for the ROM it agreed to store.
Unsealed chunk accounts are rejected before bytes enter memory.
Tampered chunk payloads fail SHA-256 leaf comparison.
Invalid Merkle paths never reach the committed root.
Wrong-owner PDAs are refused even if their bytes match.
Stale roots are ignored once a newer sealed commit exists.
simulated on-chain log
Spot-check 6 chunks
> proof console idle: waiting for spot-check request
How a game fits in Solana
01
Engine code, maps, sprites, and metadata compile into one deterministic ROM image.
02
The bundle is split across PDA accounts sized for predictable reads and upgrades.
03
Each chunk hashes into a SHA-256 Merkle root committed by the program.
04
Rent-exempt accounts hold the bytes and can return lamports when closed.
05
The browser pulls account slices with getMultipleAccounts and rebuilds the ROM.
Approximate framing for a ROM-sized payload; live market prices vary.
| Method | Write model | Read path | Reality check | Status |
|---|---|---|---|---|
| Solana Account Rent | ~0.001–0.002 SOL per 10 KB | Parallel RPC account reads | Rent-exempt balance is refundable when accounts close. | Best fit |
| EVM Calldata | Paid per byte, not refundable | Cheap to reference, costly to publish | Good for proofs, expensive for full game payloads. | Proofs only |
| EVM Contract Storage | Highest persistent write cost | State reads are available, writes dominate | Permanent state is powerful but punishing for ROM bundles. | Cost wall |
Honest status
proof
Merkle and account checks are simulated for the demo.
canvas
Three upgraded playable modes run locally after boot.
docs
Architecture copy mirrors Solana PDA storage patterns.
rent
Rent-exempt balances are modeled as refundable storage.
// SPECIFICATION & PROTOCOL DOCS
How to bundle, chunk, verify, and run immutable games and binaries from Solana account storage.
module 01
ROM bytes are segmented into deterministic Program Derived Address chunks. Each account stores a small sealed header, chunk index, payload length, payload bytes, and the root commitment it belongs to.
seeds = [b"arvex", rom_id.as_bytes(), &chunk_index.to_le_bytes()]module 02
The program verifies chunk leaves and Merkle paths inside Solana BPF/SBF with the native sol_sha256 syscall, then rejects any account that cannot prove membership against the sealed root.
initialize_rom(ctx, rom_id, chunk_count)
write_chunk(ctx, rom_id, chunk_index, bytes)
seal_rom(ctx, rom_id, merkle_root)
verify_chunk(ctx, rom_id, chunk_index, proof)module 03
The browser treats RPC data as untrusted until every chunk is hashed, ordered, and reconstructed against the on-chain root commitment.
getMultipleAccounts(pdas) -> hash leaves -> rebuild Merkle root -> inflate bundle -> instantiate memorymodule 04
A publisher packs a deterministic build folder, deploys chunk accounts to the target network, then seals the ROM id so clients can boot from an immutable root.
npx arvex-solana pack ./dist --id depth
npx arvex-solana deploy --network mainnet --keypair id.json
npx arvex-solana seal --rom-id depthinteractive examples
#[program]
pub mod arvex_solana {
pub fn initialize_rom(ctx: Context<InitializeRom>, rom_id: String, chunk_count: u32) -> Result<()> {
ctx.accounts.manifest.set_inner(RomManifest::new(rom_id, chunk_count));
Ok(())
}
pub fn write_chunk(ctx: Context<WriteChunk>, chunk_index: u32, bytes: Vec<u8>) -> Result<()> {
require!(!ctx.accounts.manifest.sealed, ArvexError::AlreadySealed);
ctx.accounts.chunk.write_payload(chunk_index, &bytes)?;
Ok(())
}
pub fn seal_rom(ctx: Context<SealRom>, merkle_root: [u8; 32]) -> Result<()> {
ctx.accounts.manifest.root = merkle_root;
ctx.accounts.manifest.sealed = true;
Ok(())
}
pub fn verify_chunk(ctx: Context<VerifyChunk>, proof: Vec<[u8; 32]>) -> Result<()> {
let bytes = ctx.accounts.chunk.data.borrow();
let leaf = solana_program::hash::hashv(&[&bytes[HEADER_LEN..]]);
verify_merkle_branch(leaf.to_bytes(), proof, ctx.accounts.manifest.root)
}
}