SOL Omnibus Staking

Implement SOL staking in an omnibus architecture - one wallet and many users

πŸ“˜

Who is this for?

Exchanges, ETPs, banks, LST and LRT protocols, and anyone staking on behalf of many users with a single or few wallets who wants to create a great UX and accurately distribute rewards

🚧

If you're new to SOL staking...

If you're new to SOL staking, check out SOL Staking 101 first

Omnibus details

An omnibus setup consolidates multiple users' staking flows into a single wallet to enhance UX. In an omnibus setup, ensure the following:

  • Accurate accounting of user balances (offchain)
  • Proportional distribution of rewards (offchain)
  • Scalable management of stake accounts for high-volume staking (onchain)

Solution: daily batching

The best practice for an omnibus setup is daily batching of user staking requests. Here's how it works:

Part 1: Create StakeAccount & merge


  1. Create a parent stake account:
    1. Via POST /stake. This account acts as the primary account for delegating SOL to Figment. You only need to do this the first time you stake
  2. Daily batching with new stake accounts:
    1. Aggregate off-chain user staking requests throughout the day until 00:00 UTC
    2. For the positive staking sum, create a new stake using POST /stake
    3. E.g. user_a requests 5 SOL stake, user_b requests 6 SOL stake, user_c requests 7 SOL stake, then at 00:00 UTC, call POST /stake for 17 SOL
  3. Merge stake accounts:
    Two stake accounts can be merged. Do this once both stake accounts are active
    1. Get the stake account status with GET /stakes
    2. Once the new stake account is active, merge it into the parent stake account (endpoint coming soon)
    3. Merging reduces the number of stake accounts to manage while maintaining an aggregated balance

Part 2: distribute Rewards

  • Fetch reward data: Use POST /rewards to retrieve historical staking reward data for your stake accounts
  • Proportional allocation: Calculate each user’s share of the rewards based on their contribution to the total staked balance as of the most recent epoch (off-chain)
    • Formula: (user_staked_amount / last_epoch_parent_staked_amount) * last_epoch_parent_rewards
  • Update user balances: Adjust user balances in the off-chain accounting system to reflect their earned rewards
  • Reward transparency: Provide users with a breakdown of their rewards, accessible through the platform
  • Optional auto-compounding: Allow users to opt-in for automatic reinvestment of their rewards into the staking pool during the next batching cycle

Part 3: Split StakeAccount & unstake


Splitting a stake account allows you to unstake any amount of SOL that you want instead of your full staked balance. E.g. if your parent stake account has 10 SOL balance and you want to unstake 3 SOL, then "split" the parent account to create a child account with 3 SOL in it then deactivate the child

Before you begin, ensure you have:

  • A funded stake account: This will serve as the source account for the split
  • Sufficient SOL in your wallet: Splitting a stake account requires paying transaction fees and funding the new account with rent-exempt SOL
  1. Split parent stake account:
    1. Identify the parent account to split with GET /stakes
    2. Split the stake accont (endpoint coming soon)
  2. Deactivate child account:
    1. Deactivate a stake account by calling POST /undelegate.
      Note: Deactivation takes ~1 epoch (~2 days) to complete
  3. Withdraw:
    1. Withdraw SOL from the deactivated stake account via POST /withdraw

Extra credit: delegate MEV rewards

MEV rewards accrue to your stake account's inactive balance and don't auto-compound like inflation rewards. To earn on them, Solana requires you to manually activate them by signing a transaction from your delegating wallet:

  1. Withdraw your MEV rewards with POST /withdraw. Omitting amount_sol withdraws all of your MEV rewards and keeps your existing stake active
  2. Delegate your withdrawn SOL with POST /stake
  3. Earn rewards next epoch!