Solana Staking Program Breakdown

Justin Lee
Metacamp
Published in
3 min readMay 9, 2022

Resource: https://github.com/step-finance/step-staking

TLDR;

Users send tokens to the token vault in exchange for an “equity” of the vault, represented as xToken. The program tracks the total amount of xToken distributed as well as the amount owned by each individual. As the vault grows from an external source of revenue, each xToken is worth more. When the user unstake, the program will calculate the user share of the vault base on the xToken.

Initialize

The program creates a Staking Account and initializes a Token Vault on initializing. The token vault is owned by the token program and holds the actual balance of the token, whereas the staking account is used to track information regarding the vault.

Initlizer_key

The public key of the vault initializer. This is used to update the lock_end_date and freeze_program.

Total_x_token

The total amount of x_token distributed.

Usage

Params:

vaultBump, stakingBump, lockEndDate

Accounts:

{ tokenMint, tokenVault, stakingAccount, initializer, systemProgram, tokenProgram, rent }

Stake (Part 1)

In this scenario, User A decided to stake 1,000 tokens into an empty vault. Because it is an empty vault, the exchange rate is set to 1. So, for 1,000 tokens, User A will receive 1,000 xTokens.

Usage

Params:

vaultBump, stakingBump, userStakingBump, amount

Accounts:

{ tokenMint, tokenFrom, tokenFromAuthority, tokenVault, stakingAccount, userStakingAccount, systemProgram, tokenProgram, rent }

Stake (Part 2)

A few minutes later, an external source of revenue yielded 300 tokens and was deposited into the token vault. User B decided to stake 3,000 tokens into the vault that now contains 1,300 tokens, 1,000 from User A, and 300 from an external source. The formula used to calculate the exchange rate for token/xToken is;

amount * total_xToken / total_token

With this, the User B will receive 2,307 xToken (3,000 * 1,000 / 1,300). Note that the staking account keeps track of the total_xToken in circulation.

Stake (Part 3)

After a couple of minutes, an external source of revenue yielded another 500 tokens and was deposited into the token vault. User C decided to stake 5,000 tokens into the vault that now contains 4,800 tokens. Using the same formula we user C will receive 3,444 xToken (5,000 * 3,307 / 4,800).

Unstake

If any of the users wish to unstake, the token amount the user will is based on the proportion of xToken the user holds. The formula used to calculate this is;

amount * token_token / total_xToken

As User A was around before the first and second revenue injection, User A would receive a total of 1,451 tokens, an addition of 451 tokens. While User B receives 3,348 tokens, an addition of 348 tokens for joining before the second revenue injection. On the other hand, User C will only receive the amount staked as there wasn’t any revenue injection.

Usage

Params:

vaultBump, stakingBump, userStakingBump, amount

Accounts:

{ tokenMint, xTokenFromAuthority, tokenVault, stakingAccount, userStakingAccount, tokenTo, tokenProgram }

Emit Reward

Usage

const res = await program.simulate.emitReward({
accounts: { tokenMint, tokenVault, stakingAccount, tokenFromAuthority, userStakingAccount }});

let reward = res.events[0].data;
console.log(‘Deposit Amount: ‘, reward.deposit.toString());
console.log(‘Reward Amount: ‘, reward.reward.toString());

--

--