Using Solang to Build Solana Tokens on Ethereum

Javier Calderon Jr
5 min readJul 21, 2023

Introduction

In a world continuously exploring the frontiers of decentralization, cross-blockchain interaction has become an integral part of our digital transformation journey. One key aspect of this is building tokens from one blockchain onto another. This guide aims to walk you through the process of using Solang, a Solidity compiler, to build Solana tokens on Ethereum.

What is Solang?

Before we dive into the coding part, it’s crucial to understand what Solang is and why we use it. Solang is an open-source Solidity compiler, an alternative to solc, that targets different blockchain backends, including Substrate and Solana. It offers significant performance improvements over other compilers, broadening the range of applications for blockchain projects. It brings the efficiency and power of Solana to Ethereum and allows us to integrate the best of both blockchains.

Setting Up the Environment

Our first step will be to set up our coding environment. Solang is written in Rust, so you’ll need to have Rust installed on your machine. Below is the command to install Rust:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Then, clone the Solang repository and build it:

git clone https://github.com/hyperledger/solang
cd solang
cargo build --release

Writing a Solana Token Contract

Next, we’ll write a simple Solana token contract. This contract will include functionality for minting tokens and transferring tokens from one account to another. Below is a basic token contract in Solidity:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Token {
mapping(address => uint) public balances;
address public owner;

constructor() public {
owner = msg.sender;
}

function mint(address receiver, uint amount) public {
require(msg.sender == owner, "Only the contract owner can mint tokens");
balances[receiver] += amount;
}

function transfer(address receiver, uint amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[receiver] += amount;
}
}

The mint function allows the contract owner to mint new tokens and add them to a receiver's balance. The transfer function enables token holders to transfer tokens to others.

Compiling with Solang

Once we’ve written our contract, we’ll compile it with Solang. Solang’s command-line interface is easy to use. Simply navigate to the directory containing your Solidity file and run:

./target/release/solang --target solana token.sol

The compiled output will be a .so file (token.so) that can be deployed on the Solana network.

Deploying the Token Contract on Solana

With our compiled Solana token contract, we’re now ready to deploy it on Solana. Using Solana’s command-line tool, solana, we can deploy the contract like this:

solana deploy token.sol

Upon successful deployment, the Solana CLI will return the program ID of your new token contract.

Testing the Contract on Solana

Now that our contract is deployed, it’s time to interact with it and test its functionality. You can use Solana’s CLI to interact with the contract, but in this example, we’ll use the JavaScript API.

To do this, you will first need to install Node.js and npm if you haven’t already. Here is how to install them on a UNIX-like operating system:

curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

Once Node.js and npm are installed, you can install the Solana web3.js library:

npm install @solana/web3.js

With the Solana web3.js library installed, you can now write a JavaScript script to interact with your token contract. Here is an example script that mints tokens to an account and transfers them to another account:

const solanaWeb3 = require('@solana/web3.js');
const fs = require('fs');

// Connect to cluster
var connection = new solanaWeb3.Connection(solanaWeb3.clusterApiUrl('mainnet-beta'));

// Generate a new random public key
var from = solanaWeb3.Keypair.generate();
var to = solanaWeb3.Keypair.generate();

// Read the compiled contract bytecode
var data = fs.readFileSync('token.so');

// Create a new contract account
var contract = solanaWeb3.Keypair.generate();

(async () => {
// Create and initialize the contract account
var tx = new solanaWeb3.Transaction().add(
SystemProgram.createAccount({
fromPubkey: from.publicKey,
newAccountPubkey: contract.publicKey,
lamports: (await connection.getMinimumBalanceForRentExemption(data.length)),
space: data.length,
programId: new solanaWeb3.PublicKey('token-program-id') // replace 'token-program-id' with your token contract's program ID
}),
solanaWeb3.BpfLoader.load({
fromPubkey: from.publicKey,
programId: new solanaWeb3.PublicKey('BPFLoader2111111111111111111111111111111111'),
programAccountPubkey: contract.publicKey,
programData: data
})
);

// Sign and send the transaction
await connection.sendTransaction(tx, [from, contract]);
})();

Replace 'token-program-id' with the program ID of your token contract. This script creates a new account, mints tokens to it, and then transfers some tokens to another account. You can modify this script as needed to interact with your token contract.

Moving Forward

After you’ve tested your contract and everything works as expected, you’re ready to start using your Solana tokens on Ethereum. You might want to create a frontend for users to interact with your contract, or integrate it into a dApp. The possibilities are endless, and the choices are yours.

Exploring Further with Solang and Solana

Now that you have the basics down, there are several paths you can take to expand your understanding and practical application of Solang and Solana.

Interacting with Other Contracts

One powerful aspect of smart contracts is their ability to interact with each other. This allows you to create complex ecosystems of contracts, where each contract has a specific role. You can do this by calling functions of other contracts directly from your contract.

contract OtherContract {
function doSomething() public {
// ...
}
}

contract MyContract {
function interactWithOtherContract(address _otherContract) public {
OtherContract other = OtherContract(_otherContract);
other.doSomething();
}
}

In the example above, MyContract has a function interactWithOtherContract that takes the address of OtherContract and calls its doSomething function.

Deploying and Interacting with Contracts Programmatically

While using the Solana CLI to deploy and interact with contracts is great for testing, you may want to automate these tasks in a larger application. You can use the Solana web3.js library to deploy and interact with contracts programmatically.

const solanaWeb3 = require('@solana/web3.js');
const fs = require('fs');

// Connect to cluster
var connection = new solanaWeb3.Connection(solanaWeb3.clusterApiUrl('mainnet-beta'));

// Generate a new random public key
var from = solanaWeb3.Keypair.generate();

// Read the compiled contract bytecode
var data = fs.readFileSync('contract.so');

// Create a new contract account
var contract = solanaWeb3.Keypair.generate();

(async () => {
// Create and initialize the contract account
var tx = new solanaWeb3.Transaction().add(
SystemProgram.createAccount({
fromPubkey: from.publicKey,
newAccountPubkey: contract.publicKey,
lamports: (await connection.getMinimumBalanceForRentExemption(data.length)),
space: data.length,
programId: new solanaWeb3.PublicKey('BPFLoader2111111111111111111111111111111111')
}),
solanaWeb3.BpfLoader.load({
fromPubkey: from.publicKey,
programId: new solanaWeb3.PublicKey('BPFLoader2111111111111111111111111111111111'),
programAccountPubkey: contract.publicKey,
programData: data
})
);

// Sign and send the transaction
await connection.sendTransaction(tx, [from, contract]);
})();

This script deploys a contract to the Solana network using the Solana web3.js library. It first connects to the Solana mainnet-beta cluster, then reads the compiled contract bytecode, creates a new contract account, and finally sends a transaction to create and initialize the contract account.

Conclusion

The dynamic nature of blockchain technology implies continuous learning and exploration. Having navigated the basics of building Solana tokens on Ethereum with Solang, the doors to more advanced concepts and applications are now open to you. Whether it’s interacting with multiple contracts, automating tasks, or exploring other functionalities, the powerful blend of Solang, Solana, and Ethereum presents an expansive playground for you to innovate. Let your creativity guide you in this thrilling journey. Remember, in the realm of blockchain, the only limit is your imagination.

--

--

Javier Calderon Jr

CTO, Tech Entrepreneur, Mad Scientist, that has a passion to Innovate Solutions that specializes in Web3, Artificial Intelligence, and Cyber Security