Why Solana Broke My Solidity Habits: Building Programs Instead of Contracts

💡 For developers who built on Ethereum and want to understand why Solana feels completely different — and why that difference matters for real-world applications.


🎯 Building Programs, Not Monoliths

When financial institutions want to tokenize real estate, bonds, or commodities, they need a blockchain that scales like traditional finance — not one that charges $50 per transaction. The answer isn't just faster code; it's a fundamentally different architecture.

Technical subtitle: From EVM monolithic state to Solana's stateless programs with PDAs and Sealevel parallel execution


📊 The Developer's Dilemma: Why Everything Feels Wrong

If you've built smart contracts on Ethereum and tried Solana, you know the feeling:

What You're Used To (Ethereum) What Solana Asks You To Do
Store data inside contracts Keep data in separate Accounts
Let the contract find its own state Pass accounts explicitly to programs
One contract = one universe One program = many independent accounts
Sequential execution Parallel processing via Sealevel

This isn't a language problem. It's a mindset shift from object-oriented thinking to data-oriented thinking.


💡 The Monolithic Model: Solidity and Global State

In Solidity, a smart contract is like a giant object. The code and the data live together. If you create a contract to manage tokens, user balances are stored in a mapping(address => uint256) within the contract itself.

The EVM Workflow:

sequenceDiagram
    participant User
    participant Contract
    participant EVM
    User->>Contract: call transfer(to, amount)
    Contract->>Contract: lookup balances[msg.sender]
    Contract->>Contract: update balances
    Contract->>EVM: save to global state
    EVM-->>User: transaction confirmed
  1. You call a function in the contract.
  2. The contract looks into its own "internal memory" for the user's balance.
  3. The contract updates that value and saves the change to the network's global state.

The problem: This model is inherently sequential. If ten people want to interact with the same contract, the network must process them one by one to prevent internal state corruption. This is the bottleneck that leads to high fees and latency.


🔄 The Graph Model: Anchor and State Separation

Solana breaks this scheme with a radical premise: Programs are stateless.

An Anchor program is simply a set of logical instructions. It does not store any data. All information (balances, configurations, identities) lives in Accounts, which act like independent files on a hard drive.

The Anchor Workflow:

sequenceDiagram
    participant Client
    participant Program
    participant AccountA
    participant AccountB
    Client->>Program: invoke instruction([AccountA, AccountB])
    Program->>AccountA: read state
    Program->>AccountB: read state
    Program->>AccountA: update state
    Program->>AccountB: update state
    Program-->>Client: instruction complete
  1. You call an instruction in the program.
  2. You (the client) must pass the program all the accounts (files) that the program will need to read or write.
  3. The program executes the logic on those accounts and closes them.

This approach allows Solana to be massively parallel. If two transactions touch different accounts, the Sealevel engine executes them simultaneously. There is no longer a single "line"; there are thousands of parallel execution threads.

graph TB
    subgraph EVM["Ethereum — Sequential"]
        T1[Transaction 1] --> C[Contract Global State]
        T2[Transaction 2] --> C
        T3[Transaction 3] --> C
    end
    
    subgraph Solana["Solana — Parallel"]
        T4[Tx: Token A] --> P[Program]
        T5[Tx: Token B] --> P
        T6[Tx: Token C] --> P
        P --> A1[Account A]
        P --> A2[Account B]
        P --> A3[Account C]
    end

🏗️ Case Study: The RWA Platform

Looking at the code in our solana-rwa repository, we can see exactly how this "graph" mindset is applied.

From a Mapping to a PDA

In Solidity, to manage multiple RWA tokens, we would likely use a complex map: mapping(bytes32 => TokenInfo).

In our Solana project, we use PDAs (Program Derived Addresses). Instead of a central map, we create a unique address for each token based on seeds: [b"token", owner, token_id].

// Simplified concept of our implementation #[derive(Accounts)] pub struct Initialize<'info> { #[account( init, payer = payer, space = 8 + TokenState::LEN, seeds = [b"token", owner.key().as_ref(), token_id.as_ref()], bump )] pub token_state: Account<'info, TokenState>, // ... other accounts }

Instead of searching within a monolith, the program "derives" the address of the data account. The state is not inside the program, but distributed across the network as accounts.

flowchart TD
    subgraph Solidity[&#34;EVM — Centralized Mapping&#34;]
        Contract[Contract Storage]
        Contract --&gt; M1[Token A Data]
        Contract --&gt; M2[Token B Data]
        Contract --&gt; M3[Token C Data]
    end
    
    subgraph Solana[&#34;Solana — Distributed PDAs&#34;]
        Program[Stateless Program]
        PDA1[PDA: Token A]
        PDA2[PDA: Token B]
        PDA3[PDA: Token C]
        Program --&gt;|&#34;derives&#34;| PDA1
        Program --&gt;|&#34;derives&#34;| PDA2
        Program --&gt;|&#34;derives&#34;| PDA3
    end

Atomic Modularity

Our architecture divides logic into three independent programs:

Program Responsibility Repository Path
solana-rwa Token logic (mint, transfer, freeze) solana-rwa/programs/rwa
identity-registry KYC verification, identity validation identity-registry/programs/registry
compliance-aggregator Rules engine, transfer validation compliance-aggregator/programs/aggregator

In EVM, this is often solved with a "Master Contract" that calls others. In Solana, these are atomic instructions that interact by passing accounts. It is a much more modular and fault-tolerant system.


📈 Impact: What This Architecture Enables

Metric Solidity Approach Anchor Approach
State Location Internal (storage) External (Accounts)
Execution Model Sequential (One by one) Parallel (Sealevel)
Data Access Internal mapping and arrays PDA Derivation
Data Responsibility Contract finds its own data Client provides data to program
Scalability Limited by global state Distributed accounts

For RWA tokenization, this means:

  • Institutional throughput: Thousands of asset transfers per second, matching traditional market speeds
  • Predictable costs: Sub-cent transaction fees, making fractional ownership economically viable
  • Regulatory compliance: Modular design allows compliance checks without modifying token logic
  • Fault isolation: A bug in one program doesn't compromise the entire system

🤔 Why This Matters Beyond Blockchain

The shift from monolithic to graph-based architecture isn't unique to blockchain. It mirrors the evolution from monolithic applications to microservices in traditional software engineering. The difference is that Solana's approach goes further: it's not just modular code — it's modular state.

This is what makes RWA tokenization viable at an institutional scale. By treating assets not as entries in a global table, but as independent and derivable accounts, we eliminate bottlenecks and open the door to a financial infrastructure that can truly compete with the speed of traditional markets.


✅ Key Takeaways

  1. Solana programs are stateless — all data lives in independent Accounts
  2. Clients provide accounts explicitly — the program doesn't search, it receives
  3. PDAs enable deterministic addresses — derived from seeds, not private keys
  4. Parallel execution is real — Sealevel processes independent transactions simultaneously
  5. Modularity is architectural, not just logical — separate programs = separate failure domains

🔗 Explore the Code

Want to see the architecture in action? Explore the solana-rwa/programs folder in our 87maxi/rwa repository:


📊 Key Metrics

Metric Value Context
EVM Gas per SSTORE ~20,000 - 50,000 Storage operation cost
Solana CU per PDA Access ~10 - 50 Zero-copy deserialization
Transaction Cost (RWA) ~$0.0001 Sub-cent fees enable micro-transactions
Max TPS (Solana) 65,000+ Parallel execution via Sealevel
Program Size Limit ~10 KB Stateless programs, modular design

🔗 Continuous Learning

🤝 Contribute

This article is part of the Solana RWA Platform open-source initiative. If you have insights on:

  • Smart contract architecture — Monolithic vs modular design patterns
  • Solana programs — PDAs, CPIs, cross-program invocation
  • RWA tokenization — Compliance, identity verification, fractional ownership

...your contribution is welcome:

  • 🐛 Report issues: github.com/87maxi/rwa/issues
  • 🔧 Pull Requests: Welcome for new program implementations
  • 💡 Discussions: Open a discussion to share ideas
💬

Comments

Powered by Giscus · GitHub Discussions

🧠 Web3 & Blockchain