Skip to main content

Solidity libraries for composability with Solana programs through NeonEVM

Overview

NeonEVM's composability feature

NeonEVM is a Solana network extension enabling EVM dApps to tap into Solana's user base and liquidity. It comes with a set of precompiled smart contracts acting as an interface between EVM dApps on NeonEVM and Solana's accounts and programs.

The composability feature allows EVM dApps deployed on NeonEVM to interact with Solana programs, which involves formatting Solana instructions in ways that are specific to each program.

Here we provide a set of Solidity libraries which make it possible to easily implement secure interactions with the following Solana programs:

  • System program: LibSystemProgram, LibSystemData and LibSystemErrors libraries
  • SPL Token program: LibSPLTokenProgram, LibSPLTokenData and LibSPLTokenErrors libraries
  • Associated Token program: : LibAssociatedTokenProgram and LibAssociatedTokenData libraries
  • Metaplex program: LibMetaplexProgram, LibMetaplexData and LibMetaplexErrors libraries
  • Raydium program: LibRaydiumCPMMProgram, LibRaydiumCPMMData and LibRaydiumCPMMErrors libraries

We also provide a set of example smart-contracts implementing typical use cases for these libraries and best practices when it comes to user authentication and Solana accounts management.

Installation

npm install @neonevm/call-solana
note

More details about the composability libraries package at npm: @neonevm/call-solana

Supported Solana programs

important

The following contracts have not been audited yet and are here for educational purposes.

Composability helper contracts

  • Constants.sol provides commonly used constants for formatting instructions to be executed by Solana programs
  • CallSolanaHelperLib.sol provides helper functions to prepare formatted instructions right before they are executed on Solana
  • SolanaDataConverterLib.sol provides helper functions for casting data to and from various types commonly used on Solana
  • ICallSolana.sol provides an interfacte to the CallSolana precompiled contract which is the cornerstone of NeonEVM's composability with Solana. See: ICallSolana interface documentation .
  • QueryAccount.sol provides a set of getter function for reading Solana's state by querying data stored on Solana accounts

Solana specifics

See: Common Solana terminology

Solana Token accounts

Associated token accounts vs Arbitrary token accounts

Arbitrary token accounts are derived using a seed which includes the token account owner's public key and an arbitrary nonce (among other parameters). By using different nonce values it is possible to derive different arbitrary token accounts for the same owner which can be useful for some use cases.

The CallSPLTokenProgram contract provides its users with methods to create and initialize SPL token mints and arbitrary token accounts as well as to mint and transfer tokens using those accounts. It features a built-in authentication logic ensuring that users remain in control of created accounts.

However, there exists a canonical way of deriving a SPL token account for a specific owner and this token account is called an Associated Token account. Associated Token accounts are used widely by application s running on Solana and it is generally expected that token transfers are made to and from Associated Token accounts.

The CallAssociatedTokenProgram contract provides a method to create and initialize canonical Associated Token accounts for third party Solana users. This method can also be used to create and initialize canonical Associated Token accounts owned by this contract.

Ownership and authentication

SPL token mint ownership and authentication

The CallSPLTokenProgram.createInitializeTokenMint function takes a seed parameter as input which is used along with msg.sender to derive the created token mint account. While the CallSPLTokenProgram contract is given mint/freeze authority on the created token mint account, the mintTokens function grants msg.sender permission to mint tokens by providing the seed that was used to create the token mint account.

Metadata accounts ownership and authentication

The CallMetaplexProgram.createTokenMetadataAccount function takes a seed parameter as input which is used along with msg.sender to derive a token mint account. Created token metadata account is associated with this token mint account which must have been created and initialized beforehand by the same msg.sender. That same msg.sender is also granted permission to update the token metadata account in the future, provided that it is set as mutable upon creation.

Arbitrary token accounts ownership and authentication

Using arbitrary SPL Token accounts created via the CallSPLTokenProgram contract deployed on NeonEVM allows for cheap and easy authentication of NeonEVM users to let them interact with and effectively control those token accounts securely via this contract while this contract is the actual owner of those token accounts on Solana. It is also possible to create and initialize an arbitrary SPL Token accounts for third party Solana users, granting them full ownership of created accounts on Solana.

The CallSPLTokenProgram.createInitializeArbitraryTokenAccount function can be used for three different purposes:

  • To create and initialize an arbitrary token account to be used by msg.sender to send tokens through the CallSPLTokenProgram contract. In this case, both the owner and tokenOwner parameters passed to the function should be left empty. The arbitrary token account to be created is derived from msg.sender and a nonce (that can be incremented to create different arbitrary token accounts). Only msg.sender is allowed to perform state changes to the created token account via this contract. The transferTokens function grants msg.sender permission to transfer tokens from this arbitrary token account by providing the nonce that was used to create the arbitrary token account.

  • To create and initialize an arbitrary token account to be used by a third party user NeonEVM account through the CallSPLTokenProgram contract. In this case, the owner parameter passed to the function should be
    CallSPLTokenProgram.getNeonAddress(user) and the tokenOwner parameter should be left empty. The arbitrary token account to be created is derived from the user account and a nonce (that can be incremented to create different arbitrary token accounts). Only that user is allowed to perform state changes to the created token account via this contract. The transferTokens function grants user permission to transfer tokens from this arbitrary token account by providing the nonce that was used to create the arbitrary token account.

  • To create and initialize an arbitrary token account to be used by a third party solanaUser Solana account to send tokens directly on Solana without interacting with the CallSPLTokenProgram contract. In this case, both the owner and the tokenOwner parameters passed to the function should be solanaUser. The arbitrary token account to be created is derived from the solanaUser account and a nonce (that can be incremented to create different arbitrary token accounts). The owner of the arbitrary token account is the solanaUser account. The solanaUser account cannot transfer tokens from this arbitrary token account by interacting with the CallSPLTokenProgram contract, instead it must interact directly with the SPL Token program on Solana by signing and executing a transfer instruction.

License

This software is licensed under the MIT license

Was this page helpful?