Feb 12, 2026

What Solana Forces You to Design For

Migrating from EVM to Solana is rarely a line-by-line rewrite. It’s an architectural adaptation.

In this article, we share lessons from real-world Solana production work, including adapting Solidity-based logic into Rust programs, addressing audit findings, implementing EIP-712–inspired signature verification with ed25519, and hardening token and claim flows.

We explore the practical constraints that shape Solana design, account-based storage, transaction size limits, instruction composition, and deterministic token accounts, and the mindset shift required when building secure, production-grade Solana programs.

Solana is not “Solidity with faster blocks”. When a team expands from EVM to Solana, the shift is real: different programming model, different storage paradigm, and different constraints.

At WakeUp Labs, we’ve been working hands-on on Solana engagements that include:

  • Adapting EVM contract logic into Solana programs

  • Token-2022 with Custom Extension Launches

  • Applying security fixes based on third-party audit reports

  • Refactoring architecture to match Solana’s account-based model

  • Hardening claims and reward distribution flows (tokens + NFTs)

This blog shares what that work looks like in practice, and lessons that repeatedly show up when shipping production-grade Solana programs.

The project pattern: rewards, claims, and chain expansion

A common pattern we see in blockchain applications is the use of incentives built around user interactions.

Users perform actions (sign up, mint, stake, interact with an app), those actions are tracked as events, and rewards are assigned and later claimed. Rewards can be fungible tokens and also NFTs.

In one engagement, the system already existed on an EVM chain (Solidity). The goal was to expand the same logic into Solana, not as a 1:1 rewrite, but as an adaptation (Solana programs require architectural changes).

The key point: the functionality stays conceptually similar (reward assignment + claim), but the implementation changes because the chain does.

“Migration” in Solana is usually an adaptation

Even if the product concept is the same, Solana isn’t a straightforward port from Solidity:

  • On EVM you write contracts in Solidity.

  • On Solana you write programs in Rust.

  • On EVM, storage is largely implicit, you “write state” inside your contract.

  • On Solana, state lives in accounts, and the transaction must include the accounts you intend to read/write.

That difference alone forces architectural decisions early:

  • What is the state?

  • Where does it live?

  • Which accounts must be passed in each instruction?

  • Which accounts must be derived deterministically? And with which seeds?

In this engagement, the client was also refactoring their own logic in parallel, so the result was explicitly not a 1:1 translation. It was a re-architecture that preserved the core business behavior.

Two Solana constraints that matter immediately

1) Transaction size limits shape design

Solana has a maximum transaction size, which becomes a practical constraint when you try to batch complex actions.

A concrete example from the work: a claim flow that depended on signature verification, where the ideal experience was “multi-signature style” (multiple verifications + claim in a single user action). In practice, the transaction size limit meant that only a limited number of verification instructions could fit. To support this flow, we have developed our own implementation of the EIP-712 standard from solidity and use ed25519 elliptic curve for verification.

This forces tradeoffs like:

  • support fewer signatures, or

  • accept multi-step flows, or

  • design a structure that can work today and expand later if the network parameters change.

2) Instructions are composable, but you must validate their coherence

Solana transactions can contain multiple instructions. That’s powerful, but it introduces a sharp edge:

If you rely on several verification instructions and then a final “claim”, you must ensure the data across those instructions is consistent.

One of the most important audit findings we addressed was exactly this:

  • The implementation extracted data from the first instruction,

  • verified signatures in the later instructions,

  • but initially didn’t verify that all instructions were signing the same underlying data.

That kind of bug is subtle, easy to miss, and can become critical in reward/claim flows.

A real failure mode: accounts must be deterministic (or you can fragment funds)

One of the most interesting Solana-specific bugs we fixed was about token accounts.

On Ethereum, your address receives any ERC-20. On Solana, users commonly have a token account per token (derived from their “main” wallet).

Here’s the catch: on Solana, the user must explicitly provide all accounts that will be read or written in a transaction, including the program’s token accounts. Because of this, it’s possible to create more than one valid token account for the same owner and mint (depending on how address derivation is handled).

If a program doesn’t enforce the expected deterministic token account for program-held tokens, a user can supply a different (but still valid) account. This can easily lead to a broken state model, such as:

  • balances scattered across multiple accounts,

  • the program’s internal accounting thinking funds are in one place,

  • transfers failing because the value isn’t consolidated where the program expects it.

In this engagement, a fix was to ensure the program verifies that the relevant token account is the expected deterministic one, instead of accepting any arbitrary account provided by the user.

If you’re shipping token movement and balances on Solana, this is a “don’t skip it” check.

3 practical lessons (good practices) from shipping this work

1) Use fast, resettable testing workflows

Solana’s default approach often leans on a local validator, which can turn the test suite into one giant integration test and slow iteration.

Moving to a faster testing setup, like liteSVM, made it easier to reset state between tests and iterate quickly, leading to tighter feedback loops and higher confidence in the code.

2) Treat signature flows as first-class security design

If your program uses “voucher-like” signed claims (to avoid onchain assignment transactions and reduce user cost), the signature design becomes your product’s security perimeter.

In practice:

  • verification might need its own instruction,

  • batching has limits,

  • and you must validate that every signature is tied to the exact same payload, not just “a valid signature”.

3) Enforce deterministic token accounts in token flows

If token accounts are not forced to be deterministic, it’s easy to accidentally accept “valid but wrong” accounts and fragment balances or break accounting.

If your program holds balances, credits users, or manages pooled funds, deterministic account enforcement is a baseline safety measure.

The mindset shift when coming from Ethereum

The biggest change isn’t Rust vs Solidity.

It’s that in Solana:

  • you explicitly manage accounts as storage,

  • you design around constraints like transaction size,

  • you rely on instruction composition (and must validate it),

  • and debugging often requires more “reading other protocols” than “just googling it”.

There’s less copy-pasteable standardization, which makes architectural discipline and testing workflows even more important.

Closing

Solana can be “more fun” and powerful, but it demands a different mental model.

The takeaway is simple: Solana work is rarely about rewriting code line-by-line. It’s about adapting architecture, hardening flows, and being extremely intentional with accounts, instructions, and signatures.

If you’re expanding an existing EVM product into Solana, these are the kinds of edges worth planning for early.

Solana is not “Solidity with faster blocks”. When a team expands from EVM to Solana, the shift is real: different programming model, different storage paradigm, and different constraints.

At WakeUp Labs, we’ve been working hands-on on Solana engagements that include:

  • Adapting EVM contract logic into Solana programs

  • Token-2022 with Custom Extension Launches

  • Applying security fixes based on third-party audit reports

  • Refactoring architecture to match Solana’s account-based model

  • Hardening claims and reward distribution flows (tokens + NFTs)

This blog shares what that work looks like in practice, and lessons that repeatedly show up when shipping production-grade Solana programs.

The project pattern: rewards, claims, and chain expansion

A common pattern we see in blockchain applications is the use of incentives built around user interactions.

Users perform actions (sign up, mint, stake, interact with an app), those actions are tracked as events, and rewards are assigned and later claimed. Rewards can be fungible tokens and also NFTs.

In one engagement, the system already existed on an EVM chain (Solidity). The goal was to expand the same logic into Solana, not as a 1:1 rewrite, but as an adaptation (Solana programs require architectural changes).

The key point: the functionality stays conceptually similar (reward assignment + claim), but the implementation changes because the chain does.

“Migration” in Solana is usually an adaptation

Even if the product concept is the same, Solana isn’t a straightforward port from Solidity:

  • On EVM you write contracts in Solidity.

  • On Solana you write programs in Rust.

  • On EVM, storage is largely implicit, you “write state” inside your contract.

  • On Solana, state lives in accounts, and the transaction must include the accounts you intend to read/write.

That difference alone forces architectural decisions early:

  • What is the state?

  • Where does it live?

  • Which accounts must be passed in each instruction?

  • Which accounts must be derived deterministically? And with which seeds?

In this engagement, the client was also refactoring their own logic in parallel, so the result was explicitly not a 1:1 translation. It was a re-architecture that preserved the core business behavior.

Two Solana constraints that matter immediately

1) Transaction size limits shape design

Solana has a maximum transaction size, which becomes a practical constraint when you try to batch complex actions.

A concrete example from the work: a claim flow that depended on signature verification, where the ideal experience was “multi-signature style” (multiple verifications + claim in a single user action). In practice, the transaction size limit meant that only a limited number of verification instructions could fit. To support this flow, we have developed our own implementation of the EIP-712 standard from solidity and use ed25519 elliptic curve for verification.

This forces tradeoffs like:

  • support fewer signatures, or

  • accept multi-step flows, or

  • design a structure that can work today and expand later if the network parameters change.

2) Instructions are composable, but you must validate their coherence

Solana transactions can contain multiple instructions. That’s powerful, but it introduces a sharp edge:

If you rely on several verification instructions and then a final “claim”, you must ensure the data across those instructions is consistent.

One of the most important audit findings we addressed was exactly this:

  • The implementation extracted data from the first instruction,

  • verified signatures in the later instructions,

  • but initially didn’t verify that all instructions were signing the same underlying data.

That kind of bug is subtle, easy to miss, and can become critical in reward/claim flows.

A real failure mode: accounts must be deterministic (or you can fragment funds)

One of the most interesting Solana-specific bugs we fixed was about token accounts.

On Ethereum, your address receives any ERC-20. On Solana, users commonly have a token account per token (derived from their “main” wallet).

Here’s the catch: on Solana, the user must explicitly provide all accounts that will be read or written in a transaction, including the program’s token accounts. Because of this, it’s possible to create more than one valid token account for the same owner and mint (depending on how address derivation is handled).

If a program doesn’t enforce the expected deterministic token account for program-held tokens, a user can supply a different (but still valid) account. This can easily lead to a broken state model, such as:

  • balances scattered across multiple accounts,

  • the program’s internal accounting thinking funds are in one place,

  • transfers failing because the value isn’t consolidated where the program expects it.

In this engagement, a fix was to ensure the program verifies that the relevant token account is the expected deterministic one, instead of accepting any arbitrary account provided by the user.

If you’re shipping token movement and balances on Solana, this is a “don’t skip it” check.

3 practical lessons (good practices) from shipping this work

1) Use fast, resettable testing workflows

Solana’s default approach often leans on a local validator, which can turn the test suite into one giant integration test and slow iteration.

Moving to a faster testing setup, like liteSVM, made it easier to reset state between tests and iterate quickly, leading to tighter feedback loops and higher confidence in the code.

2) Treat signature flows as first-class security design

If your program uses “voucher-like” signed claims (to avoid onchain assignment transactions and reduce user cost), the signature design becomes your product’s security perimeter.

In practice:

  • verification might need its own instruction,

  • batching has limits,

  • and you must validate that every signature is tied to the exact same payload, not just “a valid signature”.

3) Enforce deterministic token accounts in token flows

If token accounts are not forced to be deterministic, it’s easy to accidentally accept “valid but wrong” accounts and fragment balances or break accounting.

If your program holds balances, credits users, or manages pooled funds, deterministic account enforcement is a baseline safety measure.

The mindset shift when coming from Ethereum

The biggest change isn’t Rust vs Solidity.

It’s that in Solana:

  • you explicitly manage accounts as storage,

  • you design around constraints like transaction size,

  • you rely on instruction composition (and must validate it),

  • and debugging often requires more “reading other protocols” than “just googling it”.

There’s less copy-pasteable standardization, which makes architectural discipline and testing workflows even more important.

Closing

Solana can be “more fun” and powerful, but it demands a different mental model.

The takeaway is simple: Solana work is rarely about rewriting code line-by-line. It’s about adapting architecture, hardening flows, and being extremely intentional with accounts, instructions, and signatures.

If you’re expanding an existing EVM product into Solana, these are the kinds of edges worth planning for early.

Our latest stories:

See all posts

LogoWakeup

© 2025 - WakeUp Inc. All Rights reserved.