SolScript Solana Solidity Developer Tools

Why Solidity Developers Should Deploy on Solana (Without Learning Rust)

SolScript compiles Solidity syntax to native Solana BPF programs with automatic PDA derivation, account validation, and Anchor compatibility. A comprehensive guide to deploying on Solana without rewriting your contracts in Rust.

DS
Dipankar Sarkar
19 min read 3,606 words

Solidity developers can deploy on Solana without learning Rust by using SolScript, a compiler that takes standard Solidity syntax and produces native Solana BPF programs. SolScript handles the translation automatically — mapping mapping types to Program Derived Addresses, generating Anchor-compatible account validation structs, and compiling to BPF bytecode — so the resulting programs are indistinguishable from hand-written Anchor/Rust code on-chain.

This guide covers exactly how that works, when to use it, and what it can’t do yet.

TL;DR

  • SolScript compiles Solidity to native Solana programs (not EVM emulation — actual BPF bytecode)
  • Two compilation backends: Anchor codegen (generates readable Rust) and direct LLVM-to-BPF (maximum performance)
  • Automatic PDA derivation, account validation, SPL token operations, and CPI support
  • Current version: v0.3.0 (Beta), available on crates.io as solscript-cli
  • Built by Cryptuon, a blockchain research company based in Scotland, UK
  • Not a compatibility layer or VM — your contracts compile to the same output a Rust developer would write

The Multi-Chain Problem Is a Language Problem

Every serious DeFi protocol today faces the same question: which chains do we deploy on? Ethereum has the liquidity and network effects. Solana has sub-second finality, 65,000 TPS theoretical throughput, and transaction fees measured in fractions of a cent. The answer is increasingly “both” — and often more.

But deploying on Solana means rewriting everything. Solana’s programming model is fundamentally different from Ethereum’s:

  • Account model vs. contract storage: Ethereum contracts store state internally. Solana programs are stateless — all data lives in separate accounts that must be passed to every instruction.
  • Program Derived Addresses (PDAs): Where Ethereum uses mapping(address => uint), Solana requires deriving deterministic addresses from seeds and validating ownership.
  • Anchor framework: The dominant Solana framework requires defining account validation structs, instruction handlers, and explicit account constraints in Rust.
  • Rust itself: Ownership, borrowing, lifetimes, and traits are concepts that take months to internalize for developers coming from Solidity.

The result is that a Solidity team wanting to deploy on Solana typically needs to either hire Rust engineers (senior Rust/Solana devs command $200-350K+ in 2026) or spend 3-6 months retraining existing developers. Neither is fast. Neither is cheap.

This is the single biggest barrier to multi-chain adoption, and it has nothing to do with the blockchains themselves.

What SolScript Actually Is

SolScript is a compiler. Not an EVM emulator. Not a compatibility layer. Not a transpiler that produces unreadable intermediate code. It takes Solidity syntax — with a small set of Solana-specific annotations — and produces native Solana programs.

There are two compilation backends:

  1. Anchor Codegen: Solidity source is parsed into an AST, analyzed for storage layout and function signatures, and then code-generated into idiomatic Anchor/Rust. The output is human-readable Rust that you can inspect, modify, and audit. It then compiles through the standard Anchor toolchain to BPF bytecode.

  2. Direct LLVM-to-BPF: The Solidity AST is lowered to LLVM IR and compiled directly to Solana BPF bytecode, bypassing the Rust intermediate step. This produces smaller binaries with tighter compute budgets, but the output isn’t human-readable Rust.

Both backends produce programs that are indistinguishable from hand-written Solana programs on-chain. They use the same runtime, the same syscalls, the same account model. There is no EVM running inside Solana.

How the Compilation Pipeline Works

Understanding what SolScript does under the hood makes it clear why this approach produces better results than EVM emulation.

Solidity Source (.sol)


   ┌─────────┐
   │  Parser  │  ── Solidity syntax + @state, @public, @view annotations
   └────┬────┘


   ┌─────────┐
   │   AST    │  ── Abstract Syntax Tree with type information
   └────┬────┘

        ├──────────────────────┐
        │                      │
        ▼                      ▼
 ┌──────────────┐     ┌───────────────┐
 │ Anchor Codegen│     │ LLVM Backend  │
 │  (Backend 1)  │     │ (Backend 2)   │
 └──────┬───────┘     └──────┬────────┘
        │                      │
        ▼                      ▼
 ┌──────────────┐     ┌───────────────┐
 │  Rust/Anchor  │     │   LLVM IR     │
 │  Source Code  │     │               │
 └──────┬───────┘     └──────┬────────┘
        │                      │
        ▼                      ▼
 ┌──────────────┐     ┌───────────────┐
 │ anchor build  │     │  llc (BPF)    │
 └──────┬───────┘     └──────┬────────┘
        │                      │
        └──────────┬───────────┘


          ┌────────────────┐
          │  Solana BPF     │
          │  Program (.so)  │
          └────────────────┘

The key transformations that happen during compilation:

Storage Layout to Account Structure: Each @state variable in your Solidity contract becomes a field in a Solana account struct. SolScript calculates the byte layout, derives the PDA seeds, and generates the deserialization logic.

Mappings to PDAs: A mapping(address => uint64) in Solidity becomes a PDA derived from the mapping key. SolScript generates the seed derivation ([b"mapping_name", key.as_ref()]) and the find_program_address call automatically.

Function Signatures to Instructions: Each @public function becomes a Solana instruction with the appropriate account context struct. SolScript analyzes which state the function reads and writes, then generates the minimal account set with correct mut and signer constraints.

SPL Token Calls to CPIs: transfer(), mint(), and burn() calls are recognized as SPL Token operations and compiled to Cross-Program Invocations against the SPL Token program.


Technical Walkthrough: Three Real Examples

The best way to understand SolScript is to see what it does. Here are three complete examples, ordered by complexity.

Example 1: Counter Program

The simplest possible stateful program — a counter that can be incremented and read.

// counter.sol
contract Counter {
    @state
    uint64 count;

    @public
    function increment() {
        count += 1;
    }

    @view
    function getCount() returns (uint64) {
        return count;
    }
}

What SolScript generates (Anchor codegen backend):

use anchor_lang::prelude::*;

declare_id!("CounterProgramID11111111111111111111111111111");

#[program]
pub mod counter {
    use super::*;

    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        let state = &mut ctx.accounts.state;
        state.count += 1;
        Ok(())
    }

    pub fn get_count(ctx: Context<GetCount>) -> Result<u64> {
        Ok(ctx.accounts.state.count)
    }
}

#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut, seeds = [b"state"], bump)]
    pub state: Account<'info, CounterState>,
    #[account(mut)]
    pub authority: Signer<'info>,
}

#[derive(Accounts)]
pub struct GetCount<'info> {
    #[account(seeds = [b"state"], bump)]
    pub state: Account<'info, CounterState>,
}

#[account]
pub struct CounterState {
    pub count: u64,
}

Notice what SolScript handled automatically:

  • The @state annotation on count became a CounterState account struct with PDA seeds [b"state"]
  • The @public annotation on increment generated a Signer constraint for authorization
  • The @view annotation on getCount generated a read-only account context (no mut)
  • Account validation, bump derivation, and serialization are all generated

Example 2: SPL Token Contract

A token contract that can mint, transfer, and burn — mapping directly to SPL Token operations.

// token.sol
contract MyToken {
    @state
    address mintAuthority;

    @state
    uint64 totalSupply;

    @public
    function initialize(address authority) {
        mintAuthority = authority;
        totalSupply = 0;
    }

    @public
    function mint(address to, uint64 amount) {
        require(msg.sender == mintAuthority, "Unauthorized");
        spl.mintTo(to, amount);
        totalSupply += amount;
    }

    @public
    function transfer(address from, address to, uint64 amount) {
        require(msg.sender == from, "Not owner");
        spl.transfer(from, to, amount);
    }

    @public
    function burn(address from, uint64 amount) {
        require(msg.sender == from, "Not owner");
        spl.burn(from, amount);
        totalSupply -= amount;
    }
}

SolScript recognizes spl.mintTo(), spl.transfer(), and spl.burn() as SPL Token operations and generates the corresponding CPIs. The require() statements become Anchor require!() macros with custom error types. The msg.sender reference compiles to a signer check against the transaction’s signing account.

This is a critical difference from EVM emulation approaches: the resulting program interacts directly with Solana’s SPL Token program through CPI, meaning tokens created this way are fully compatible with every Solana wallet, DEX, and tool.

Example 3: Escrow Program

A two-party escrow that holds tokens until both parties deposit, then swaps atomically.

// escrow.sol
contract Escrow {
    @state
    address partyA;

    @state
    address partyB;

    @state
    uint64 amountA;

    @state
    uint64 amountB;

    @state
    bool depositedA;

    @state
    bool depositedB;

    @public
    function initialize(
        address _partyA,
        address _partyB,
        uint64 _amountA,
        uint64 _amountB
    ) {
        partyA = _partyA;
        partyB = _partyB;
        amountA = _amountA;
        amountB = _amountB;
        depositedA = false;
        depositedB = false;
    }

    @public
    function depositA() {
        require(msg.sender == partyA, "Not party A");
        require(!depositedA, "Already deposited");
        spl.transfer(msg.sender, self, amountA);
        depositedA = true;
    }

    @public
    function depositB() {
        require(msg.sender == partyB, "Not party B");
        require(!depositedB, "Already deposited");
        spl.transfer(msg.sender, self, amountB);
        depositedB = true;
    }

    @public
    function execute() {
        require(depositedA && depositedB, "Both parties must deposit");
        spl.transfer(self, partyB, amountA);
        spl.transfer(self, partyA, amountB);
    }

    @public
    function cancel() {
        require(msg.sender == partyA || msg.sender == partyB, "Not a party");
        require(!(depositedA && depositedB), "Cannot cancel after both deposits");

        if (depositedA) {
            spl.transfer(self, partyA, amountA);
            depositedA = false;
        }
        if (depositedB) {
            spl.transfer(self, partyB, amountB);
            depositedB = false;
        }
    }
}

This compiles to a full Anchor program with:

  • A PDA-based escrow state account
  • Token account management for both parties
  • CPI calls to SPL Token for deposits and withdrawals
  • Proper signer validation on every instruction
  • Cancellation logic with partial refunds

The Anchor codegen backend produces approximately 180 lines of Rust for this escrow — code that would take a Rust-native developer a day to write and debug, and a Solidity developer several weeks to learn enough Rust to attempt.


SolScript vs. Alternatives: A Detailed Comparison

SolScript is not the only way to bring Solidity to Solana. Here’s how the major approaches compare.

FeatureSolScriptNeon EVMSolangNative Anchor/Rust
ApproachCompiles Solidity to native BPFRuns full EVM inside SolanaCompiles Solidity to BPF via LLVMWrite Rust directly
OutputNative Solana programEVM bytecode on SolanaNative Solana programNative Solana program
Runtime overheadNone — compiles to nativeSignificant — full EVM emulationMinimal — LLVM-compiledNone
SPL Token compatibilityDirect CPI integrationWrapped tokens via proxyLimited supportFull native access
Anchor compatibilityFull (codegen backend)None — different paradigmPartialFull (is Anchor)
PDA supportAutomatic derivationN/A (uses EVM storage)ManualManual
Transaction costSame as native programs10-50x higher (EVM overhead)Same as native programsSame as native programs
DebuggingVS Code LSP, readable Rust outputRemix/Hardhat (familiar)Limited toolingFull Anchor tooling
MaturityBeta (v0.3.0)ProductionDeprecated/stalledProduction
Learning curve for Solidity devsLow — Solidity + annotationsLowest — unchanged SolidityModerate — Solidity + Solana conceptsHighest — learn Rust + Anchor
Composability with Solana DeFiFull native composabilityLimited (EVM sandbox)Full native composabilityFull native composability
Maintained byCryptuonNeon LabsSolana Labs (reduced)Coral/Anchor community

When to Use Each

Use SolScript when you want native Solana performance with Solidity syntax, need direct SPL token integration and composability with Solana DeFi, and have a team that knows Solidity but not Rust. The Anchor codegen backend is particularly valuable when you need auditable, readable intermediate code.

Use Neon EVM when you need to deploy an existing Ethereum contract on Solana with zero code changes and are willing to accept higher transaction costs and limited composability with native Solana programs. This is the fastest path for a proof-of-concept, but the performance overhead makes it impractical for high-frequency DeFi.

Use Solang cautiously. While it was an early mover in Solidity-to-Solana compilation, development has slowed significantly. If you’re starting a new project today, SolScript’s active development and broader feature set (PDA derivation, Anchor compatibility, VS Code tooling) make it a stronger choice.

Use native Anchor/Rust when you need maximum control over compute budget optimization, have complex CPI chains, or are building infrastructure-level programs. If your team already knows Rust, there’s no reason to add a compilation layer. Anchor is mature, well-documented, and battle-tested.


The Business Case: ROI of SolScript

Let’s be specific about costs. The numbers below are based on publicly available salary data, typical audit pricing, and estimates from teams we’ve worked with.

Engineering Costs

ScenarioWithout SolScriptWith SolScript
Team compositionSolidity team + Rust teamSolidity team only
Additional hiring2-3 senior Rust/Solana devs ($250K+ each)0 additional hires
Training time3-6 months for Solidity devs to learn Rust1-2 days to learn SolScript annotations
Codebase maintenance2 codebases (Solidity + Rust)1 codebase (Solidity)
Feature parity lagWeeks to port features across codebasesSame-day deployment to both chains

Audit Costs

Security audits are priced by codebase size and complexity. A typical DeFi protocol audit costs $50-200K per codebase. With SolScript:

  • Single source of truth: One Solidity codebase, one audit scope
  • Generated code is deterministic: The Anchor output is predictable, reducing auditor time
  • Anchor codegen backend: Auditors can review the generated Rust, applying standard Anchor audit methodologies

This doesn’t eliminate the need for a Solana-specific audit — you still need to verify that the generated code handles Solana’s account model correctly. But it reduces the scope from “audit an entire Rust codebase” to “verify the compiler output against the Solidity source.”

Time to Market

For a team with 3 Solidity contracts (e.g., a DEX with a router, liquidity pool, and governance token):

  • Without SolScript: 3-6 months to rewrite and test in Rust
  • With SolScript: 1-2 weeks to compile, test, and deploy

The difference is not just engineering time — it’s market timing. In DeFi, being six months late to a new chain often means the opportunity has passed.


Getting Started: Step by Step

Prerequisites

  • Rust toolchain (1.70+)
  • Solana CLI (1.17+)
  • Anchor (0.29+) — required for the Anchor codegen backend
  • Node.js (18+) — for testing with Anchor’s TypeScript test framework

Step 1: Install SolScript

cargo install solscript-cli

Verify the installation:

solscript --version
# solscript-cli 0.3.0

Step 2: Write Your Contract

Create a file called counter.sol:

contract Counter {
    @state
    uint64 count;

    @public
    function increment() {
        count += 1;
    }

    @view
    function getCount() returns (uint64) {
        return count;
    }
}

Step 3: Compile to Solana

Using the Anchor codegen backend (recommended for inspecting output):

solscript compile counter.sol --target solana --backend anchor

This generates a full Anchor project in ./output/counter/ with the Rust program, Anchor.toml, and test scaffolding.

Using the direct LLVM backend (smaller binaries, no intermediate Rust):

solscript compile counter.sol --target solana --backend llvm

Step 4: Build and Test

cd output/counter
anchor build
anchor test

The generated test suite includes basic instruction tests for every @public function.

Step 5: Deploy

Deploy to Solana devnet:

solana config set --url devnet
anchor deploy

Deploy to mainnet-beta:

solana config set --url mainnet-beta
anchor deploy

Step 6: IDE Support

Install the SolScript VS Code extension for:

  • Syntax highlighting for SolScript annotations (@state, @public, @view)
  • Real-time compilation errors via the Language Server Protocol (LSP)
  • Inline display of generated Rust code
  • Go-to-definition support across the Solidity-to-Rust boundary

Search for “SolScript” in the VS Code extension marketplace, or install from the command line:

code --install-extension cryptuon.solscript-vscode

Limitations: What SolScript Can’t Do Yet

SolScript is in beta (v0.3.0). Being honest about its current limitations is as important as explaining its capabilities.

Not Yet Supported

  • Token 2022 extensions: Transfer hooks, confidential transfers, and other Token 2022 features are not yet supported. Planned for v0.4.0.
  • Compute budget optimization: SolScript-generated programs use default compute budgets. Manual compute unit tuning is on the v0.4.0 roadmap.
  • Metaplex integration: NFT-specific operations (metadata, collections, editions) require the Metaplex program and are planned for v0.4.0.
  • Versioned transactions: V0 transactions and address lookup tables are not yet supported. Planned for v0.5.0.
  • Cross-chain messaging: Wormhole integration for cross-chain CPI is on the v0.5.0 roadmap.

Structural Limitations

  • Not all Solidity features map cleanly: Solana’s programming model is fundamentally different from Ethereum’s. Features like delegatecall, reentrancy guards (Solana doesn’t have reentrancy), and inline assembly don’t have direct Solana equivalents. SolScript will emit a compilation error rather than silently producing incorrect code.
  • Gas model differences: Solana uses compute units, not gas. SolScript does not attempt to simulate Ethereum gas semantics — your Solidity code must be aware that it’s targeting Solana’s execution environment.
  • Contract size limits: Solana programs have a maximum size of ~1.2MB (upgradeable) or ~10KB (non-upgradeable BPF). Complex Solidity contracts may exceed these limits when compiled.
  • Inheritance and interfaces: Multi-level inheritance and interface-heavy patterns common in Ethereum (e.g., OpenZeppelin’s inheritance trees) are partially supported. Simple inheritance works; complex diamond inheritance patterns may require restructuring.

When to Use Native Rust Instead

SolScript is the right tool for many projects, but not all. Consider writing native Anchor/Rust when:

  • You need fine-grained control over compute unit optimization for high-frequency programs
  • Your program involves complex multi-instruction CPI chains with many accounts
  • You’re building core infrastructure (AMMs, orderbooks, lending protocols) where every compute unit matters
  • Your team already has Rust expertise

Roadmap

SolScript’s development is active and milestone-driven.

v0.3.0 (Current — Beta)

  • Anchor codegen backend
  • Direct LLVM-to-BPF backend
  • Automatic PDA derivation
  • Account validation generation
  • SPL Token operations (transfer, mint, burn)
  • CPI support
  • VS Code extension with LSP
  • Comprehensive examples: counter, token, escrow, voting, NFT, staking, AMM

v0.4.0 (Upcoming)

  • Token 2022 extension support
  • Compute budget controls
  • Metaplex NFT integration
  • Improved error messages and diagnostics

v0.5.0 (Planned)

  • Versioned transactions (V0)
  • Address lookup tables
  • Wormhole cross-chain messaging integration
  • Advanced CPI patterns

Development is tracked publicly. If you need a specific feature prioritized, contact us.


Frequently Asked Questions

Is SolScript production-ready?

SolScript is in beta (v0.3.0). The compiler is functional and produces correct output for the supported feature set — counter, token, escrow, voting, NFT, staking, and AMM patterns have all been tested. However, “beta” means the API may change between versions, and we recommend thorough testing and an independent audit before mainnet deployment. Teams deploying to mainnet today should use the Anchor codegen backend so the generated Rust can be reviewed by Solana-native auditors.

How does SolScript differ from Neon EVM?

Neon EVM runs a full Ethereum Virtual Machine inside Solana, executing EVM bytecode on-chain. SolScript compiles Solidity to native Solana BPF programs — no EVM involved at runtime. This means SolScript-compiled programs have the same performance characteristics as hand-written Anchor programs, use standard Solana transaction fees, and compose natively with other Solana programs (SPL tokens, Raydium, Jupiter, etc.). Neon EVM programs run in an isolated EVM environment with higher costs and limited composability. See the comparison table above for a full breakdown.

Can I use existing OpenZeppelin contracts with SolScript?

Not directly. OpenZeppelin contracts are designed for the EVM and rely on patterns (delegatecall proxies, ERC-20 interfaces, reentrancy guards) that don’t map to Solana’s execution model. SolScript supports Solidity syntax, not the entire Ethereum ecosystem. You’ll need to write contracts using SolScript’s annotations (@state, @public, @view) and SPL token operations instead of ERC-20 interfaces. That said, the logic in your OpenZeppelin-based contracts (access control, math, state management) is straightforward to port to SolScript syntax.

What happens to the generated Rust code — can I modify it?

Yes, when using the Anchor codegen backend. SolScript generates idiomatic, well-structured Anchor/Rust code that you can read, modify, and maintain. Some teams use SolScript for the initial code generation and then switch to maintaining the Rust code directly. This is a valid workflow — SolScript reduces the cold-start problem even if you eventually want full Rust control. The LLVM backend, by contrast, produces binary output that isn’t designed for manual modification.

Do I need Rust installed to use SolScript?

Yes. SolScript itself is a Rust binary (cargo install solscript-cli), and the Anchor codegen backend compiles through the standard Anchor/Rust toolchain. You don’t need to write Rust, but you need the Rust toolchain installed. The LLVM backend also requires LLVM to be installed for the final BPF compilation step.

How do I test SolScript-compiled programs?

SolScript generates Anchor-compatible test scaffolding alongside the compiled program. You can use Anchor’s standard TypeScript testing framework (anchor test), which uses Bankrun or solana-test-validator under the hood. The testing workflow is identical to any other Anchor project — write TypeScript tests, call instructions, assert account state. If your team already tests Solidity contracts with Hardhat or Foundry, the Anchor test framework will feel familiar: setup accounts, call functions, check results.


Conclusion

The multi-chain future is here, but the tooling hasn’t kept up. Solidity developers shouldn’t need to become Rust experts to deploy on Solana, and Solana shouldn’t miss out on the largest pool of smart contract developers in the ecosystem.

SolScript closes that gap by compiling Solidity to native Solana programs — no EVM emulation, no performance penalty, no walled garden. The Anchor codegen backend gives you readable, auditable Rust. The LLVM backend gives you optimized BPF bytecode. Both produce programs that are first-class citizens on Solana.

It’s beta software. There are limitations. But for the patterns it supports today — token contracts, escrows, governance, staking, basic AMMs — it works, and it eliminates months of Rust ramp-up time.

Install it, try the counter example, and see what the generated Anchor code looks like. If it fits your use case, you just saved your team a quarter.

cargo install solscript-cli
solscript compile counter.sol --target solana --backend anchor

For integration support, custom compilation targets, or enterprise licensing, reach out to our team. For more on Cryptuon’s blockchain infrastructure tooling, see our solutions overview or browse our published research.

DS

Dipankar Sarkar

Founder, Cryptuon

Blockchain researcher and systems engineer. Author of 5 published papers on cross-chain composability, MEV mitigation, and DePIN protocols. Building production blockchain infrastructure in Rust and Zig.

Build on research-grade infrastructure

Ready to deploy smart contracts across chains, execute atomic cross-rollup swaps, or protect your validators from slashing?