Nosana Staking
Nosana Staking
The staking program allows users to stake NOS
tokens for a variable amount of time.
The staking dashboard can be found here: https://explorer.nosana.io/stake/
There are 2 values associated with a users stake:
- Staked NOS
- xNOS (Staked NOS x duration)
The staked NOS is the amount of tokens that the vault actually holds for the user that can be slashed or unstaked,
while xNOS is a value indicating a users rank for purposes like giveaways and voting.
Program Information
Info | Description |
---|---|
Type | Solana Program |
Source Code | GitHub |
Build Status | Anchor Verified |
Accounts | 3 |
Instructions | 10 |
Types | 0 |
Errors | 13 |
Domain | nosana-staking.sol |
Address | nosScmHY2uR24Zh751PmGj9ww9QRNHewh9H59AfrTJE |
Instructions
A number of 10 instruction are defined in the Nosana Staking program.
To load the program with Anchor.
const programId = new PublicKey('nosScmHY2uR24Zh751PmGj9ww9QRNHewh9H59AfrTJE');
const idl = await Program.fetchIdl(programId.toString());
const program = new Program(idl, programId);
Init
Initialize the SettingsAccount.
Account Info
The following 4 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
settings | The SettingsAccount address. | |
authority | The signing authority of the program invocation. | |
systemProgram | The official Solana system program address. Responsible for system CPIs. | |
rent | The official Solana rent address. Responsible for lamports. |
Solana Dispatch ID
The Solana dispatch ID for the Init Instruction
is dc3bcfec6cfa2f64
,
which can also be expressed as an 8 byte discriminator:
[220,59,207,236,108,250,47,100]
Example with Anchor
To invoke the Init Instruction
with Anchor TS.
let tx = await program.methods
.init()
.accounts({
settings, // β writable, π signer
authority, // β writable, β signer
systemProgram, // π writable, π signer
rent, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Stake
Create a StakeAccount and VaultAccount.
Stake amount
of NOS tokens for duration
fo seconds.
Account Info
The following 8 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
mint | The token Mint address for this instruction. | |
user | The user token account that will debit/credit the tokens. | |
vault | The VaultAccount address. | |
stake | The StakeAccount address. | |
authority | The signing authority of the program invocation. | |
systemProgram | The official Solana system program address. Responsible for system CPIs. | |
tokenProgram | The official SPL Token Program address. Responsible for token CPIs. | |
rent | The official Solana rent address. Responsible for lamports. |
Arguments
The following 2 arguments should also be provided when invoking this instruction.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
amount | u64 | 8 | 0 | The number of tokens. |
duration | u128 | 16 | 8 | The duration of the stake. |
Solana Dispatch ID
The Solana dispatch ID for the Stake Instruction
is ceb0ca12c8d1b36c
,
which can also be expressed as an 8 byte discriminator:
[206,176,202,18,200,209,179,108]
Example with Anchor
To invoke the Stake Instruction
with Anchor TS.
let tx = await program.methods
.stake(
amount, // type: u64
duration, // type: u128
)
.accounts({
mint, // π writable, π signer
user, // β writable, π signer
vault, // β writable, π signer
stake, // β writable, π signer
authority, // β writable, β signer
systemProgram, // π writable, π signer
tokenProgram, // π writable, π signer
rent, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Unstake
Start the unstake duration.
Account Info
The following 3 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
stake | The StakeAccount address. | |
reward | The RewardAccount address. | |
authority | The signing authority of the program invocation. |
Solana Dispatch ID
The Solana dispatch ID for the Unstake Instruction
is 5a5f6b2acd7c32e1
,
which can also be expressed as an 8 byte discriminator:
[90,95,107,42,205,124,50,225]
Example with Anchor
To invoke the Unstake Instruction
with Anchor TS.
let tx = await program.methods
.unstake()
.accounts({
stake, // β writable, π signer
reward, // π writable, π signer
authority, // π writable, β signer
})
.signers([authorityKey])
.rpc();
Restake
Make a stake active again and reset the unstake time.
Account Info
The following 3 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
vault | The VaultAccount address. | |
stake | The StakeAccount address. | |
authority | The signing authority of the program invocation. |
Solana Dispatch ID
The Solana dispatch ID for the Restake Instruction
is 61a1f1a70620d535
,
which can also be expressed as an 8 byte discriminator:
[97,161,241,167,6,32,213,53]
Example with Anchor
To invoke the Restake Instruction
with Anchor TS.
let tx = await program.methods
.restake()
.accounts({
vault, // β writable, π signer
stake, // β writable, π signer
authority, // π writable, β signer
})
.signers([authorityKey])
.rpc();
Topup
Top-up amount
of NOS of a StakeAccount.
Account Info
The following 5 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
user | The user token account that will debit/credit the tokens. | |
vault | The VaultAccount address. | |
stake | The StakeAccount address. | |
authority | The signing authority of the program invocation. | |
tokenProgram | The official SPL Token Program address. Responsible for token CPIs. |
Arguments
The following 1 arguments should also be provided when invoking this instruction.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
amount | u64 | 8 | 0 | The number of tokens. |
Solana Dispatch ID
The Solana dispatch ID for the Topup Instruction
is 7e2a314ee197634d
,
which can also be expressed as an 8 byte discriminator:
[126,42,49,78,225,151,99,77]
Example with Anchor
To invoke the Topup Instruction
with Anchor TS.
let tx = await program.methods
.topup(
amount, // type: u64
)
.accounts({
user, // β writable, π signer
vault, // β writable, π signer
stake, // β writable, π signer
authority, // π writable, β signer
tokenProgram, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Extend
Extend the duration
of a StakeAccount.
Account Info
The following 2 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
stake | The StakeAccount address. | |
authority | The signing authority of the program invocation. |
Arguments
The following 1 arguments should also be provided when invoking this instruction.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
duration | u64 | 8 | 0 | The duration of the stake. |
Solana Dispatch ID
The Solana dispatch ID for the Extend Instruction
is e47f0001e39a36a8
,
which can also be expressed as an 8 byte discriminator:
[228,127,0,1,227,154,54,168]
Example with Anchor
To invoke the Extend Instruction
with Anchor TS.
let tx = await program.methods
.extend(
duration, // type: u64
)
.accounts({
stake, // β writable, π signer
authority, // π writable, β signer
})
.signers([authorityKey])
.rpc();
Close
Close a StakeAccount and VaultAccount.
Account Info
The following 5 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
user | The user token account that will debit/credit the tokens. | |
stake | The StakeAccount address. | |
vault | The VaultAccount address. | |
authority | The signing authority of the program invocation. | |
tokenProgram | The official SPL Token Program address. Responsible for token CPIs. |
Solana Dispatch ID
The Solana dispatch ID for the Close Instruction
is 62a5c9b16c41ce60
,
which can also be expressed as an 8 byte discriminator:
[98,165,201,177,108,65,206,96]
Example with Anchor
To invoke the Close Instruction
with Anchor TS.
let tx = await program.methods
.close()
.accounts({
user, // β writable, π signer
stake, // β writable, π signer
vault, // β writable, π signer
authority, // β writable, β signer
tokenProgram, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Withdraw
Withdraw NOS that is released after an unstake
Account Info
The following 5 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
user | The user token account that will debit/credit the tokens. | |
vault | The VaultAccount address. | |
stake | The StakeAccount address. | |
authority | The signing authority of the program invocation. | |
tokenProgram | The official SPL Token Program address. Responsible for token CPIs. |
Solana Dispatch ID
The Solana dispatch ID for the Withdraw Instruction
is b712469c946da122
,
which can also be expressed as an 8 byte discriminator:
[183,18,70,156,148,109,161,34]
Example with Anchor
To invoke the Withdraw Instruction
with Anchor TS.
let tx = await program.methods
.withdraw()
.accounts({
user, // β writable, π signer
vault, // β writable, π signer
stake, // β writable, π signer
authority, // β writable, β signer
tokenProgram, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Slash
Reduce a StakeAccount's NOS tokens.
Slashing is a feature used by the Nosana Protocol to punish bad actors.
Account Info
The following 6 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
vault | The VaultAccount address. | |
stake | The StakeAccount address. | |
tokenAccount | The token account where slash deposits will go. | |
settings | The SettingsAccount address. | |
authority | The signing authority of the program invocation. | |
tokenProgram | The official SPL Token Program address. Responsible for token CPIs. |
Arguments
The following 1 arguments should also be provided when invoking this instruction.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
amount | u64 | 8 | 0 | The number of tokens. |
Solana Dispatch ID
The Solana dispatch ID for the Slash Instruction
is cc8d12a108b15c8e
,
which can also be expressed as an 8 byte discriminator:
[204,141,18,161,8,177,92,142]
Example with Anchor
To invoke the Slash Instruction
with Anchor TS.
let tx = await program.methods
.slash(
amount, // type: u64
)
.accounts({
vault, // β writable, π signer
stake, // β writable, π signer
tokenAccount, // β writable, π signer
settings, // π writable, π signer
authority, // π writable, β signer
tokenProgram, // π writable, π signer
})
.signers([authorityKey])
.rpc();
Update Settings
Update the Slashing Authority and Token Account.
Account Info
The following 4 account addresses should be provided when invoking this instruction.
Name | Type | Description |
---|---|---|
newAuthority | The new authority of the SettingsAccount. | |
tokenAccount | The token account where slash deposits will go. | |
settings | The SettingsAccount address. | |
authority | The signing authority of the program invocation. |
Solana Dispatch ID
The Solana dispatch ID for the Update Settings Instruction
is 51a633d59e549d6c
,
which can also be expressed as an 8 byte discriminator:
[81,166,51,213,158,84,157,108]
Example with Anchor
To invoke the Update Settings Instruction
with Anchor TS.
let tx = await program.methods
.updateSettings()
.accounts({
newAuthority, // π writable, π signer
tokenAccount, // π writable, π signer
settings, // β writable, π signer
authority, // π writable, β signer
})
.signers([authorityKey])
.rpc();
Accounts
A number of 3 accounts make up for the Nosana Staking Program's state.
Settings Account
The SettingsAccount
struct holds the information about the
slashing authority and token account.
The total size of this account is 72
bytes.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
authority | publicKey | 32 | 8 | The signing authority of the program invocation. |
tokenAccount | publicKey | 32 | 40 | The token account where slash deposits will go. |
Anchor Account Discriminator
The first 8 bytes, also known as Anchor's 8 byte discriminator, for the Settings Account
are 3f59cb9b4ced733a
, which can also be expressed in byte array:
[63,89,203,155,76,237,115,58]
Stake Account
The StakeAccount
struct holds all the information for any given stake.
The total size of this account is 121
bytes.
Name | Type | Size | Offset | Description |
---|---|---|---|---|
amount | u64 | 8 | 8 | The number of tokens. |
authority | publicKey | 32 | 16 | The signing authority of the program invocation. |
duration | u64 | 8 | 48 | The duration of the stake. |
timeUnstake | i64 | 16 | 56 | n/a |
vault | publicKey | 32 | 72 | The VaultAccount address. |
vaultBump | u8 | 1 | 104 | The bump for the VaultAccount. |
xnos | u128 | 16 | 105 | n/a |
Anchor Account Discriminator
The first 8 bytes, also known as Anchor's 8 byte discriminator, for the Stake Account
are 509e437c32bdc0ff
, which can also be expressed in byte array:
[80,158,67,124,50,189,192,255]
Vault Account
The VaultAccount
is a regular Solana Token Account.
Errors
A number of 13 errors are defined in the Nosana Staking Program.
Nosana Error
6000
- Amount Not Enough
This amount is not enough.
Nosana Error
6001
- Already Initialized
This stake is already running.
Nosana Error
6002
- Already Claimed
This stake is already claimed.
Nosana Error
6003
- Already Staked
This stake is already staked.
Nosana Error
6004
- Already Unstaked
This stake is already unstaked.
Nosana Error
6005
- Not Unstaked
This stake is not yet unstaked.
Nosana Error
6006
- Locked
This stake is still locked.
Nosana Error
6007
- Duration Too Short
This stake duration is not long enough.
Nosana Error
6008
- Duration Too Long
This stake duration is too long.
Nosana Error
6009
- Does Not Exist
This stake account does not exist.
Nosana Error
6010
- Decreased
This stake is not allowed to decrease.
Nosana Error
6011
- Has Reward
This stake still has a reward account.
Nosana Error
6012
- Invalid Stake Account
This stake does not belong to the authority.
Diagram
xNOS calculation
For people that like to know exactly how Nosana calculate a stakers's
we've written it down as a function
Where
The
which represents the duration a staker has staked his or her tokens.
The parameter
The stake duration
such that
Because it's somewhat difficult to intuitively understand numbers of this magnitude,
we can simplify above function to use days rather seconds, which are denoted
The stake duration
such that
In more simple phrasing.
A staker can stake Nosana Tokens for a minimum of two weeks and a maximum of one year.
The longer the duration of a stake, the higher the multiplier against the number of tokens in stake.
The maximum multiplier is this system is
On the Nosana website you can find a xNOS calculator.