Skip to content

Marinade Native Staking#

Marinade Native lets you stake SOL directly with 100+ validators in a single transaction, without smart contract risk. You retain full custody of your stake accounts while Marinade handles validator selection and rebalancing.

Overview#

Feature Description
Custody Non-custodial - you keep withdraw authority
Smart Contract No smart contract risk
Validators 100+ validators via SAM
Fees Zero management fees
Unstaking ~1 epoch (~2 days)
PSR Protection Yes

Users staking through Marinade Native authorize Marinade to manage delegation while keeping the withdraw authority of their stake accounts. You always retain full control to withdraw your SOL.

How It Works#

graph LR
    A[Deposit SOL] --> B[Stake Accounts Created]
    B --> C[Marinade Sets Stake Authority]
    C --> D[Distributed to 100+ Validators]
    D --> E[Earn Rewards Every Epoch]
    E --> F[Unstake Anytime]
  1. You deposit SOL → Stake accounts are created with you as withdraw authority
  2. Marinade manages delegation → Automatically distributes across top validators
  3. Rewards accrue → Added to your stake accounts each epoch
  4. Unstake when ready → Instant (small fee) or delayed (free)

Choose Your Product#

Product Strategy Best For Validators
Max Yield Optimizes for highest APY Maximum returns All SAM validators
Select Curated high-quality set Conservative approach Premium validators only
Recipes Custom strategies Advanced users Configurable

Which should I choose?

  • Max Yield - Best for most users who want the highest returns
  • Select - Best for users who prefer a more conservative, curated validator set

Configuration#

Description Value
Marinade Stake authority stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq
Marinade Exit authority ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N
Operator opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP
API endpoint https://native-staking.marinade.finance
TypeScript
// pnpm i @marinade.finance/native-staking-sdk '@solana/web3.js
import { Connection } from '@solana/web3.js'
import { NativeStakingConfig, NativeStakingSDK } from '@marinade.finance/native-staking-sdk'

const config = new NativeStakingConfig({
    connection: new Connection('https://api.mainnet-beta.solana.com', 'confirmed'),
    stakeAuthority: new PublicKey('stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq'),
    exitAuthority: new PublicKey('ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N'),
    nativeStakingApiUrl: 'https://native-staking.marinade.finance',
    beneficiary: new PublicKey('opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP'),
})
const sdk = new NativeStakingSDK(config)
Bash
export RPC_URL='https://api.mainnet-beta.solana.com'
export STAKE_AUTHORITY='stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq'
export EXIT_AUTHORITY='ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N'
export BENEFICIARY='opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP'
export NATIVE_STAKING_API='https://native-staking.marinade.finance'
Text Only
| Description              | Value                                            |
|--------------------------|--------------------------------------------------|
| Marinade Stake authority | `stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq`    |
| Marinade Exit authority  | `ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N`    |
| Operator                 | `opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP`    |
| API endpoint             | `https://native-staking-dev.marinade.finance`    |
TypeScript
// pnpm i @marinade.finance/native-staking-sdk '@solana/web3.js
import { Connection } from '@solana/web3.js'
import { NativeStakingConfig, NativeStakingSDK } from '@marinade.finance/native-staking-sdk'

const config = new NativeStakingConfig({
    connection: new Connection('https://api.devnet.solana.com', 'confirmed'),
    stakeAuthority: new PublicKey('stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq'),
    exitAuthority: new PublicKey('ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N'),
    nativeStakingApiUrl: 'https://native-staking-dev.marinade.finance',
    beneficiary: new PublicKey('opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP'),
})
const sdk = new NativeStakingSDK(config)
Bash
export RPC_URL='https://api.devnet.solana.com'
export STAKE_AUTHORITY='stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq'
export EXIT_AUTHORITY='ex9CfkBZZd6Nv9XdnoDmmB45ymbu4arXVk7g5pWnt3N'
export BENEFICIARY='opNS8ENpEMWdXcJUgJCsJTDp7arTXayoBEeBUg6UezP'
export NATIVE_STAKING_API='https://native-staking-dev.marinade.finance'
Description Value
Marinade Stake authority STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps
Marinade Exit authority EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6
Operator opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L
API endpoint https://ns-prime.marinade.finance
TypeScript
// pnpm i @marinade.finance/native-staking-sdk '@solana/web3.js
import { Connection } from '@solana/web3.js'
import { NativeStakingConfig, NativeStakingSDK } from '@marinade.finance/native-staking-sdk'

const config = new NativeStakingConfig({
    connection: new Connection('https://api.mainnet-beta.solana.com', 'confirmed'),
    stakeAuthority: new PublicKey('STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps'),
    exitAuthority: new PublicKey('EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6'),
    nativeStakingApiUrl: 'https://ns-prime.marinade.finance',
    beneficiary: new PublicKey('opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L'),
})
const sdk = new NativeStakingSDK(config)
Bash
export RPC_URL='https://api.mainnet-beta.solana.com'
export STAKE_AUTHORITY='STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps'
export EXIT_AUTHORITY='EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6'
export BENEFICIARY='opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L'
export NATIVE_STAKING_API='https://ns-prime.marinade.finance'
Description Value
Marinade Stake authority STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps
Marinade Exit authority EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6
Operator opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L
API endpoint https://ns-prime-dev.marinade.finance
TypeScript
// pnpm i @marinade.finance/native-staking-sdk '@solana/web3.js
import { Connection } from '@solana/web3.js'
import { NativeStakingConfig, NativeStakingSDK } from '@marinade.finance/native-staking-sdk' // (1)

const config = new NativeStakingConfig({
    connection: new Connection('https://api.devnet.solana.com', 'confirmed'),
    stakeAuthority: new PublicKey('STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps'),
    exitAuthority: new PublicKey('EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6'),
    nativeStakingApiUrl: 'https://ns-prime-dev.marinade.finance',
    beneficiary: new PublicKey('opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L'),
})
const sdk = new NativeStakingSDK(config)
Bash
export RPC_URL='https://api.devnet.solana.com'
export STAKE_AUTHORITY='STNi1NHDUi6Hvibvonawgze8fM83PFLeJhuGMEXyGps'
export EXIT_AUTHORITY='EX1Fs34ajye3BTMSjTkMdZ8P4hb99vQFWzmueqhKGpH6'
export BENEFICIARY='opiNSvKm1aPkbuSjnZfY5vyJUmaVxuQyTJt6jnNTW1L'
export NATIVE_STAKING_API='https://ns-prime-dev.marinade.finance'
Description Value
Marinade Stake authority stRcP4kVnCNubspkcP3BXEthPfZFEriQBqSczDDwmYH
Marinade Exit authority exRcSuzu5XLZYZ4GgeWYDn9qYwQnBycmyG8zBDJhEgY
Operator opRcXCJNdjujMcekTdRjZ7vibxKbM9nyAgQdXVt8kuR
API endpoint https://ns-recipes.marinade.finance
TypeScript
// pnpm i @marinade.finance/native-staking-sdk '@solana/web3.js
import { Connection } from '@solana/web3.js'
import { NativeStakingConfig, NativeStakingSDK } from '@marinade.finance/native-staking-sdk'

const config = new NativeStakingConfig({
    connection: new Connection('https://api.mainnet-beta.solana.com', 'confirmed'),
    stakeAuthority: new PublicKey('stRcP4kVnCNubspkcP3BXEthPfZFEriQBqSczDDwmYH'),
    exitAuthority: new PublicKey('exRcSuzu5XLZYZ4GgeWYDn9qYwQnBycmyG8zBDJhEgY'),
    nativeStakingApiUrl: 'https://ns-recipes.marinade.finance',
    beneficiary: new PublicKey('opRcXCJNdjujMcekTdRjZ7vibxKbM9nyAgQdXVt8kuR'),
})
const sdk = new NativeStakingSDK(config)
Bash
export RPC_URL='https://api.mainnet-beta.solana.com'
export STAKE_AUTHORITY='stRcP4kVnCNubspkcP3BXEthPfZFEriQBqSczDDwmYH'
export EXIT_AUTHORITY='exRcSuzu5XLZYZ4GgeWYDn9qYwQnBycmyG8zBDJhEgY'
export BENEFICIARY='opRcXCJNdjujMcekTdRjZ7vibxKbM9nyAgQdXVt8kuR'
export NATIVE_STAKING_API='https://ns-recipes.marinade.finance'

Marinade Stake Authority#

Stake accounts with this stake authority set are actively managed by Marinade. See Marinade operations for further details.

Marinade Exit Authority#

This authority is a part of Marinade's state management. Stake accounts with this stake authority set are marked for de-activation. Once stake accounts are de-activated, the stake accounts are merged and users can withdraw the prepared unstaked balance in a single transaction. See Delayed Unstake for further details.

Start staking#

To start staking using Marinade Native, it is necessary to:

  1. Create a stake account (ideally initialized state)
  2. Set stake authority to Marinade
TypeScript
// const config = ...
// const sdk = ...

const { connection } = useConnection() // from @solana/wallet-adapter-react
const { sendTransaction, signTransaction, publicKey } = useWallet() // from @solana/wallet-adapter-react
import BN from 'bn.js'

const amount = new BN('2000000000') // 2 SOL

const { createAuthorizedStake, stakeKeypair } = sdk.buildCreateAuthorizedStakeInstructions(publicKey, amount)

const { blockhash } = await connection.getLatestBlockhash()
const tx = new VersionedTransaction(new TransactionMessage({
    payerKey: publicKey,
    recentBlockhash: blockhash,
    instructions: createAuthorizedStake,
}).compileToV0Message())

tx.sign([stakeKeypair]) // add signature of the stake account
await signTransaction(tx) // add signature of the user
await sendTransaction(tx, connection)
Bash
WITHDRAW_AUTHORITY=... # Path to file wallet
WITHDRAW_AUTHORITY_PUBKEY=$(solana-keygen pubkey "$WITHDRAW_AUTHORITY")
SEED=$(openssl rand -hex 16) # Any seed up to 32 characters will do
BLOCKHASH=$(solana block -u "$RPC_URL" --commitment finalized --output json | jq '.blockhash' -r)

solana create-stake-account \
    -u "$RPC_URL" \
    --commitment finalized \
    -k "$WITHDRAW_AUTHORITY" \
    --seed "$SEED" \
    --blockhash "$BLOCKHASH" \
    --stake-authority "$STAKE_AUTHORITY" \
    "$WITHDRAW_AUTHORITY" "$AMOUNT"

# Optionally trigger immediate re-balancing without waiting for normal schedule
curl -sfLS "${NATIVE_STAKING_API}/v1/rebalance-hint" \
    -X POST \
    -H 'Content-type: application/json' \
    --data "$(jq --null-input -c --arg user "$WITHDRAW_AUTHORITY_PUBKEY" '{ user: $user }')"

Stop Staking#

There are three ways to unstake from Marinade Native:

Instant Unstake#

Skip the cooldown period by using Marinade's liquidity router:

  1. Go to app.marinade.finance
  2. Navigate to ManageNative Stake
  3. Select your stake accounts
  4. Choose Instant Unstake
  5. Pay a small fee (~0.1-0.3%) and receive SOL immediately

Note

Instant unstake uses liquidity pools, so fees vary based on available liquidity.

Delayed Unstake#

Standard Solana unstaking with no fees:

  1. Go to app.marinade.finance
  2. Navigate to ManageNative Stake
  3. Select your stake accounts
  4. Choose Delayed Unstake
  5. Wait ~1 epoch (~2 days) for deactivation
  6. Withdraw your SOL
Bash
# Prepare stake for revoke (delayed unstake)
WITHDRAW_AUTHORITY=... # Path to file wallet
AMOUNT=10 # Amount in SOL to unstake

WITHDRAW_AUTHORITY_PUBKEY=$(solana-keygen pubkey "$WITHDRAW_AUTHORITY")
BLOCKHASH=$(solana block -u "$RPC_URL" --commitment finalized --output json | jq '.blockhash' -r)

# Create memo with unstake request
MEMO=$(jq --null-input -c --arg user "$WITHDRAW_AUTHORITY_PUBKEY" --arg amount "$AMOUNT" '{
    PrepareForRevoke: { user: $user, amount: ((($amount | tonumber) * 1e9) | tostring) }
}')

# Send transfer with memo to signal unstake intent
REVOKE_RESULT=$(solana transfer \
    -u "$RPC_URL" \
    --commitment finalized \
    -k "$WITHDRAW_AUTHORITY" \
    --blockhash "$BLOCKHASH" \
    --with-memo "$MEMO" \
    "$BENEFICIARY" 0.0023)

REVOKE_SIGNATURE=$(echo "$REVOKE_RESULT" | awk '/Signature: / { print $2 }')

# Notify API to process the unstake
curl -sfLS "${NATIVE_STAKING_API}/v1/prepare-for-revoke" \
    -X POST \
    -H 'Content-type: application/json' \
    --data "$(jq --null-input -c \
        --arg user "$WITHDRAW_AUTHORITY_PUBKEY" \
        --arg amount "$AMOUNT" \
        --arg signature "$REVOKE_SIGNATURE" \
        '{
            signature: $signature,
            user: $user,
            amount: ((($amount | tonumber) * 1e9) | tostring)
        }')"

Manual Unstake#

This is not a recommended way of stopping staking with Marinade - this is a way to be used in case of emergency/apocalyptic-like scenarions when Marinade's UI is not available for whatever reason and you want to withdraw funds back to your wallet.

  1. Install Solana CLI using Solana's official documentation.

  2. If using a hardware wallet, discover wallet to be used with the CLI:

    Bash
    solana-keygen pubkey "usb://ledger?key=0"
    

    Tip: If you use multiple derived addresses, try changing the number at the end of the command, so e.g. solana-keygen pubkey "usb://ledger?key=1" or solana-keygen pubkey "usb://ledger?key=1/0"

    Tip: For the device to be discoverable through solana-keygen CLI, the device must not be in use by e.g. browser extension at the same time.

  3. Find your stake accounts using:

    Bash
    solana stakes --withdraw-authority YOUR-PUBLIC-KEY-GOES-HERE
    
    Example output
    Stake Pubkey: 4mFGSGdeMZsfnAh58g9PpxFN5KtcqHWQRpZVBgxnFoLH
    Balance: 1000 SOL
    Rent Exempt Reserve: 0.00228288 SOL
    Stake account is undelegated
    Stake Authority: stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq # (1)
    Withdraw Authority: YOUR-PUBLIC-KEY-IS-HERE
    
    Stake Pubkey: C6kBqxp2tvxvMaXz2FPN1f1iiQJD3R25N8kdM9PnxVXP
    Balance: 1000.048358174 SOL
    Rent Exempt Reserve: 0.00228288 SOL
    Delegated Stake: 1000.046075294 SOL
    Active Stake: 1000.046075294 SOL
    Delegated Vote Account Address: 4f9n6atJ9jDXBfTCkk4tJAACq2amnW4rAEZUkg61Zbw7 # (2)
    Stake Authority: stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq # (3)
    Withdraw Authority: YOUR-PUBLIC-KEY-IS-HERE
    

    1. This is Marinade's stake authority
    2. Validator's public key
    3. This is Marinade's stake authority

    In the example above, there are 2 stake accounts listed:

    • 4mFGSGdeMZsfnAh58g9PpxFN5KtcqHWQRpZVBgxnFoLH - this one is undelegated (could be because of some re-balancing by Marinade)
    • C6kBqxp2tvxvMaXz2FPN1f1iiQJD3R25N8kdM9PnxVXP - this one is delegated
  4. The account which is NOT delegated, is NOT activating and is NOT in the de-activation process can be withdrawn using a single command:

    Bash
    solana withdraw-stake --keypair "usb://ledger?key=0" 4mFGSGdeMZsfnAh58g9PpxFN5KtcqHWQRpZVBgxnFoLH YOUR-PUBLIC-KEY ALL
    

    Tip: 4mFGSGdeMZsfnAh58g9PpxFN5KtcqHWQRpZVBgxnFoLH is a public key of the stake account, see the example above. You will have to adjust this part of the command after you find your own stake accounts.

    Tip: Notice the ALL at the end of the command. This can be replaced by a number and you can control how much you are withdrawing.

  5. The account which IS activated or activating can be withdrawn in the following steps:

    Regain the stake authority, so you can control the delegation state of the account:

    Bash
    solana stake-authorize --keypair "usb://ledger?key=0" --new-stake-authority YOUR-PUBLIC-KEY-GOES-HERE  C6kBqxp2tvxvMaXz2FPN1f1iiQJD3R25N8kdM9PnxVXP
    

    Tip: C6kBqxp2tvxvMaXz2FPN1f1iiQJD3R25N8kdM9PnxVXP is a public key of the stake account, see the examples above. You will have to adjust this part of the command after you find your own stake accounts.

    Now de-activate the account:

    Bash
    solana deactivate-stake --keypair "usb://ledger?key=0" C6kBqxp2tvxvMaXz2FPN1f1iiQJD3R25N8kdM9PnxVXP
    

    Solana has a cool-down period of 1 epoch. So just wait for the end of the current epoch (you can see the progress using solana epoch-info). Your account will be fully de-activated and you will be able to withdraw as in the example above.

Checking Stake Balances#

You can check the status of your stake accounts using the following shell script:

Bash
WITHDRAW_AUTHORITY=... # Path to file wallet
WITHDRAW_AUTHORITY_PUBKEY=$(solana-keygen pubkey "$WITHDRAW_AUTHORITY")
EPOCH=$(solana -u "$RPC_URL" epoch)

echo "Wallet balance: $(solana -u "$RPC_URL" balance "$WITHDRAW_AUTHORITY_PUBKEY")"

# Show stakes managed by Marinade
solana stakes -u "$RPC_URL" --output json --withdraw-authority "$WITHDRAW_AUTHORITY_PUBKEY" | jq -r --arg epoch "$EPOCH" --arg authority "$STAKE_AUTHORITY" '
    .[]
    | select(.staker == $authority)
    | {
        stake: .stakePubkey,
        delegated: ((.delegatedStake//0) / 1e9),
        balance: ((.accountBalance//0) / 1e9),
        validator: .delegatedVoteAccountAddress,
        status: (if .activationEpoch == null then "initialized"
            elif .deactivationEpoch == null then
                if .activationEpoch < ($epoch | tonumber) then "active" else "activating" end
            else
                if .deactivationEpoch < ($epoch | tonumber) then "inactive" else "deactivating" end
            end)
    }'

Marinade operations#

Once the stake account's stake authority is updated, Marinade then: - Splits the original stake account into smaller stake accounts and delegates them to validators. - Periodically de-activates/delegates/merges/splits accounts in the following epochs to ensure ideal distribution of stake. - Periodically Collects extra balance from stake accounts into a reserve account, so it can be delegated.

This way, users preserve withdraw authority and even in case of black-swan event have absolute control of their stake accounts and can withdraw SOL using the Solana's native Stake Program.

Security Model#

Marinade Native uses a Program Derived Address (PDA) as the stake authority for managed stake accounts. This PDA is owned and controlled by a Solana smart contract, which itself is governed by an on-chain SPL multisig.

The SPL multisig enables decentralized control over the stake authority. Only file wallets permitted by the multisig can sign transactions on behalf of the stake authority. If a security incident occurs, the multisig can update or replace the permitted file wallet, ensuring rapid response and mitigation.

Importantly, the worst-case scenario for a compromised stake authority is that an attacker could undelegate stake from validators. However, since withdraw authority remains with the user, no funds can be lost or withdrawn by the attacker. Users always retain full control over their SOL and can withdraw at any time using Solana's native Stake Program.

Frequently Asked Questions#

Is my SOL safe with Native Staking?

Yes. You retain withdraw authority over your stake accounts at all times. Marinade only has stake authority (controls delegation). Even if Marinade were compromised, the worst case is your stake gets undelegated - your funds cannot be taken.

What's the difference between Native Staking and Liquid Staking?
Aspect Native Staking Liquid Staking
Receive Stake accounts mSOL token
DeFi usable No Yes
Smart contract risk No Yes (audited)
Custody Full (you own accounts) Non-custodial
How do I see my rewards?

Your rewards are automatically added to your stake account balances each epoch. Check your stake accounts via:

  • Marinade UI: Manage → Native Stake
  • CLI: solana stakes --withdraw-authority YOUR_PUBKEY
  • Solscan or Solana Explorer
Can I use a Ledger hardware wallet?

Yes! Native staking works with Ledger. Connect through Phantom or Solflare, or use the Solana CLI directly. See the Manual Unstake section for CLI examples.

What happens if a validator I'm staked to performs poorly?

PSR (Protected Staking Rewards) compensates you from the validator's bond if they underperform. Additionally, Marinade automatically rebalances stake away from poorly performing validators.

How many stake accounts will I have?

Marinade creates multiple stake accounts to distribute your SOL across validators. The exact number depends on your stake amount and Marinade's rebalancing strategy.

Next Steps#

Action Link
Compare with Liquid Staking Liquid Staking
Understand rewards Rewards Guide
Learn about PSR Protected Staking Rewards
Stake now app.marinade.finance