In this SoLang tutorial I’ll show you how to deploy Solidity code on Solana. We will start by setting up a dev environment before looking at some of the nuances in writing SoLang contracts. I’ll end on a few security considerations and a comparison to developing on Solana with SoLang vs Rust.
- Setting Up A Dev Environment
- HelloWorld SoLang Contract
- Deploying Solidity To Solana
- Writing SoLang Solidity
- Solana SoLang Security
- SoLang vs Rust
Setting Up A Dev Environment
At time of writing it’s advised to use a unix based dev environment. If you are on Windows this means installing windows subsystem for linux and getting familiar with the command line.
You’ll also need the following applications installed:
- Rust
- NodeJS
- Yarn
- Solana Tool Suite
- Anchor Framework
From the command line on linux (ubutnu) we can use the following commands to install these packages:
sudo apt update
sudo apt install -y rustc
sudo apt install -y nodejs
sudo apt install yarn
sudo sh -c "$(curl -sSfL https://release.solana.com/v1.16.6/install)"
export PATH="/root/.local/share/solana/install/active_release/bin:$PATH"
sudo apt install -y pkg-config build-essential libudev-dev libssl-dev
cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
avm install latest
avm use latest
There is also a VScode plugin specifically for SoLang if you want to use it as a syntax highlighter and compiler.
HelloWorld SoLang Contract
To setup a new contract we can use the following command
anchor init helloworld --solidity
This will setup a directory structure with an example contract and unit tests. Let’s take a look at a Solidity hello world contract for Solana in SoLang.
@program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
contract starter {
bool private value = true;
@payer(payer)
constructor(address payer) {
print("Hello, World!");
}
function flip() public {
value = !value;
}
function get() public view returns (bool) {
return value;
}
}
There are two unfamiliar lines here for Solidity devs.
- The @program_id() declaration at the top of the contract represents the contract address. In Solana we need to declare the storage address for the contract when we deploy/migrate it.
- The @payer() declaration is called prior to the constructor argument which accepts a payer account. The payer is a wallet address that pays the storage rental fees for the contract.
The unit tests in tests/helloworld.ts uses the anchor framework and should look quite familiar to anyone that has used the hardhat/chai testing libraries in the past.
Storage on Solana
Storage on Solana works differently to the Ethereum virtual machine and contracts can’t store state variables directly. When deploying a contract a second “storage account” will be created to hold that data, which in the contract above is a boolean true/false value.
Persistent state storage is rented rather than purchased and micropayments will be collected automatically from the payer account declared above. In practice most contracts are rent-exempt.
Each program (smart contract) has access to its own storage account or memory allocation. Programs can read any part of the global memory, but can only write in their own accounts. The one exception to this is for increasing account balances.
Solana accounts, smart contracts and storage accounts are all forms of data which live in the shared persistent memory of the nodes on the network.
Deploying Solidity To Solana
The program_id is a PDA (program derived address) and we need to set this prior to deployment. To get a new program_id() for the contract we can run the following commands:
anchor build
anchor keys list
We then need to update the ./Anchor.toml file and the ./solidity/helloworld.sol with the new program_id.
[programs.mainnet]
helloworld = "C1Fy5i8gcn2eD8YAKFcxmKfvZEr7yvmWvYi4pVnKcJKE"
We also need a wallet address setup and here I’ll be using a relatively insecure file system wallet to test with.
solana-keygen new --outfile ./key1.json
Make a note of the public key and send it some SOL to pay for deployment/transaction costs. You can buy SOL on most centralized exchanges such as Binance.
We are then going to update the ./Anchor.toml file with our wallet json file.
[provider]
cluster = "mainnet"
wallet = "./key1.json"
We then run the following command to deploy the contract
solana config set -u mainnet -k ./key1.json
anchor deploy
Note. If you get an error: “Error: No such file or directory (os error 2)” try exporting the path for the solana cli:
export PATH="/root/.local/share/solana/install/active_release/bin:$PATH"
Writing SoLang Solidity
The first thing I would recommend for developers is taking a look at the Solana developers github repository which contains a number of example SoLang smart contracts.
https://github.com/solana-developers/program-examples
Note some of the libraries available such as:
- spl_token.sol – helper functions to create new SPL tokens
- mpl_metadata.sol – library for handling Metaplex metadata
- system_instruction.sol – used to execute Solana’s system instructions
There are some additional Solana native SoLang functions to the ones we’ve looked at already (program_id() & payer()):
- @seed() set a custom seed for the deriving of the program_id
- @bump() derive program_id from specific seeds
- @space() allocate a custom amount of bytes storage for the program
SoLang isn’t a fully compatible EVM chain that you can just fork Uniswap to and it will work. It’s a compiler which is turning Solidity into bytecode to run on Solana which has very different architecture to EVM chains.
It provides a way for Solidity devs to work on Solana without having to learn a whole new language but there is still a learning curve to the infrastructure and tooling.
Solana SoLang Security
The system_instruction.sol file includes the following warning:
Although it is production ready, it has not been audited for security, so use it at your own risk.
The SoLang compiler is relatively new and there are likely going to be bugs in how it compiles Solidity contracts. Things that you take for granted in Solidity should be tested in the compiled code.
We saw this week how a Curve pool got drained because the Vyper compiler had an issue implementing re-entrancy checks. I think it’s likely we will see some issues like this in SoLang which will eventually get ironed out as the platform matures.
There is also a repository of Solana specific attack vectors which developers should familiarise themselves with here: https://github.com/coral-xyz/sealevel-attacks/tree/master
SoLang vs Rust
Solana was primarily built around Rust smart contracts and all the infrastructure and dev tooling is focused on that currently. I don’t believe that SoLang will take Rust’s place as the first language of Solana and in the short term it will be a secondary language with less market share across the ecosystem, similar to Vyper on Ethereum.
So as a developer coming to Solana should you be using SoLang or Rust?
I think this depends widely on your experience with both. I have been using Solidity for a number of years and have only worked on a couple of hobby projects using Rust. For this reason I am very grateful to all the contributors who built SoLang and enabled me to deploy Solidity code on Solana.
However if you have no predisposition over either language I believe Rust would still be the better choice for most developers coming to Solana for the first time. Rust is great, devs love it and it’s been used in Solana contracts for a number of years. In comparison SoLang is new and we are just figuring out its nuances and compatibility issues.
Devs wanted an EVM chain running on Solana which would make it easy to fork any Solidity code. SoLang isn’t that but perhaps it is more valuable that we have an alternative run time environment to the EVM where we can now use the same programming language.
There is value in diversity and SoLang is a welcome addition to the Solidity developers options.