Skip to main content
Version: Endpoint V2

Solana Guidance

This page provides development guidance for building on Solana. While some entries are LayerZero-specific, others cover general topics and tooling relevant to the Solana ecosystem.

Deploying Solana programs with a priority fee

This section applies if you are unable to land your deployment transaction due to network congestion.

Priority Fees are Solana's mechanism to allow transactions to be prioritized during periods of network congestion. When the network is busy, transactions without priority fees might never be processed. It is then necessary to include priority fees, or wait until the network is less congested.

Priority fees are calculated as follows: priorityFee = compute budget * compute unit price. We can make use of priority fees by attaching the --with-compute-unit-price flag to our solana program deploy command. Note that the flag takes in a value in micro lamports, where 1 micro lamport = 0.000001 lamport.

For example:

solana program deploy --program-id target/deploy/oft-keypair.json target/verifiable/oft.so -u devnet --with-compute-unit-price <COMPUTE_UNIT_PRICE_IN_MICRO_LAMPORTS>

You can refer QuickNode's Solana Priority Fee Tracker to know what value you'd need to pass into the --with-compute-unit-price flag.

Deciding the number of local decimals for your Solana OFT

As OFTs can span across VMs, with each VM potentially using a different data type for token amounts, it's important to understand the concept of decimals in the context of OFTs.

Make sure you understand shared decimals and local decimals before proceeding.

Before running the pnpm hardhat lz:oft:solana:create command, you should have decided the number of values to pass in for both the --shared-decimals and --local-decimals params.

For --shared-decimals, it should be the same across all your OFTs regardless of VM. Inconsistent values (i.e. one chain having a share decimals value of 4 while another has it as 6) can result in value loss. For more detail, read Token Transfer Precision.

On EVM chains, the data type that represents token amounts is uint256 and the common number of (local) decimals is 18. This results in an astronomically high possible max supply value.

(2^256 - 1) / 10^18 ≈ 1.1579 × 10^59 // (1.1579 million trillion trillion trillion trillion trillion)

In practice, tokens are typically created with a manually set max supply, for example: 1 billion (1 × 10⁹), 50 trillion (5 × 10¹³) or 1 quadrillion ( 1 × 10¹⁵).

Solana uses the u64 type to represent token amounts, with the decimals value defaulting to 9, although many tokens choose to go with 6 decimals. The possible max value by default (~18 billion) is a lot lower, so it's important to select a local decimals value on Solana that can fit your token's max supply.

Refer to the table below for a comparison between a Solana token's (local) decimals and the possible max supply value.

Max Supply in Solana for a Given Decimals Value (Decimals 9 to 4)

DecimalsMax Supply (in whole tokens)
9~1.84 × 10¹⁰ ( ~18 billion )
8~1.84 × 10¹¹ ( ~184 billion )
7~1.84 × 10¹² ( ~1.8 trillion )
6~1.84 × 10¹³ ( ~18 trillion )
5~1.84 × 10¹⁴ ( ~184 trillion )
4~1.84 × 10¹⁵ ( ~1.8 quadrillion )

Squads Multisig – Multisig Account vs Vault

In Squads, there are two distinct address types:

  • Multisig Account – the primary account that manages the Squad.
  • Vault – a derived account (at a specific index) where assets and program interactions occur.

For a deeper explanation, refer to the official Squads documentation: Vault and Multisig Address.

When using LayerZero Hardhat Helpers with the --multisig flag:

  • Provide the Multisig Account address, not the Vault address.
  • The helper internally derives the Vault address at index 0 to propose transactions to.

Creating a Squads Multisig on Solana Devnet

Squads is the most widely used multisig on Solana. The current version of Squads is v4. The OFT tasks support the usage of a Squads via the --multisig param. On mainnet, you can create a v4 Multisig using the Mainnet UI.

On the devnet UI, you are currently not able to create a multisig. However, you can still perform operations such as voting on transactions and executing them.

In order to create a Squads v4 Multisig for Solana Devnet, you have two options: CLI and Typescript SDK.

Creating using the CLI

With the Squads CLI installed, you can run:

multisig-create --rpc-url <RPC_URL> --keypair <KEYPAIR_PATH> --members <MEMBER_1> <MEMBER_2> ... --threshold <THRESHOLD>

For full context and instructions, refer to https://docs.squads.so/main/development/cli/commands#multisig-create

Creating using the Typescript SDK

Dependencies:

"@solana-developers/helpers": "^2.5.6",
"@solana/web3.js": "^1.98.0",
"@sqds/multisig": "^2.1.3",

Here is a minimal script for creating a multisig via the Typescript SDK:

import * as multisig from '@sqds/multisig';
import {Connection, Keypair, clusterApiUrl} from '@solana/web3.js';
import {getKeypairFromFile} from '@solana-developers/helpers';

const {Permission, Permissions} = multisig.types;

(async () => {
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed'); // or "mainnet-beta" for mainnet

// Signers
const creator = await getKeypairFromFile(); // first member + fee-payer
// const secondMember = Keypair.generate(); // second member // if you add another member, remember to update the threshold if not going for 1 of N

const createKey = Keypair.generate(); // seed for the PDA (must sign)

// Derive PDA for the multisig. This will be the multisig account address.
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});

const programConfigPda = multisig.getProgramConfigPda({})[0];
const programConfig = await multisig.accounts.ProgramConfig.fromAccountAddress(
connection,
programConfigPda,
);
const configTreasury = programConfig.treasury;

const sig = await multisig.rpc.multisigCreateV2({
connection,
createKey, // must sign
creator, // must sign & pays fees
multisigPda,
threshold: 1, //
timeLock: 0, // no timelock
configAuthority: null,
rentCollector: null,
treasury: configTreasury,
members: [
{key: creator.publicKey, permissions: Permissions.all()},
// { key: secondMember.publicKey, permissions: Permissions.fromPermissions([Permission.Vote]) },
],
});
const latestBlockhashInfo = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature: sig,
blockhash: latestBlockhashInfo.blockhash,
lastValidBlockHeight: latestBlockhashInfo.lastValidBlockHeight,
});
console.log(`Multisig account: ${multisigPda.toBase58()}`);
console.log(`Multisig creation txn link: https://solscan.io/tx/${sig}?cluster=devnet`);
})();

Using the created Multisig Account in the Squads Devnet UI

In the Squads v4 Devnet UI, on the initial page load you'll be asked to fill up the value for the Multisig Config Address. Input the address of the Multisig Account you had just created.

If the page is not loading, try updating the Settings to use a private RPC URL. Also ensure that the RPC in use is for Solana Devnet and not Mainnet Beta.

Implementing Time-locks for Solana OFT Mints

The Solana OFT Program's mint function cannot be altered without breaking cross-chain transfers. If you require the ability to implement time-locks for minting operations, the timelock must be configured via an additional minter and NOT on the program's mint function itself.

To implement time-locks for mints:

  • Specify additional minters when creating the OFT
  • Configure the timelock on the additional minter authority
  • Ensure the timelock is NOT applied directly to the program's mint function

Using Squads Multisig for Time-locked Mints

The additional minter can be a Squads Multisig, which you can configure to have a timelock for minting transactions. This approach allows you to implement secure time-delayed minting while preserving cross-chain transfer functionality.

When configuring a Squads Multisig as an additional minter:

  1. Set up the Squads Multisig as described in the previous section
  2. Configure the desired timelock duration for the multisig transactions
  3. Specify the multisig address as an additional minter when deploying your OFT

For more information on configuring time-locks with Squads, refer to the Squads Time-locks documentation.