BStaking

BStaking stakes bTokens to earn reserve-denominated protocol fees, including deposit, withdraw, claim, accumulator views, events, errors, and JSON ABI for integrations.

Overview

BStaking handles bToken staking and pro-rata protocol fee rewards. A reward accumulator streams pool fees and pays them in the reserve asset, so each staker's claim grows with the pool, not a fixed rate. The main drivers are:

  1. Share of total stake: staked amount over total staked
  2. Time staked: rewards accrue over time with the position
  3. Trading volume: more pool fees mean more rewards to distribute

The pattern is designed to stay fair for early and late stakers. See getAccumulator, getEarned, and getCurrentRate for the current reward state.

Functions

Staking functions

deposit

Stakes bTokens to earn rewards. The caller transfers _amount bTokens into the protocol, while _user receives the staking position.

function deposit(BToken _bToken, address _user, uint256 _amount) external
ParameterTypeDescription
_bTokenBTokenThe bToken to stake
_useraddressUser receiving the stake position
_amountuint256Amount of bTokens to stake

withdraw

Withdraw unlocked staked bTokens for msg.sender.

function withdraw(BToken _bToken, uint256 _amount) external
ParameterTypeDescription
_bTokenBTokenThe staked bToken
_amountuint256Amount to withdraw

withdrawMax

Withdraw all currently unlocked bTokens for msg.sender.

function withdrawMax(BToken _bToken) external
ParameterTypeDescription
_bTokenBTokenThe staked bToken

withdrawAndClaim

Withdraw _amount of unlocked staked bTokens and claim pending rewards in one call.

function withdrawAndClaim(BToken _bToken, uint256 _amount) external
ParameterTypeDescription
_bTokenBTokenThe staked bToken
_amountuint256bToken amount to withdraw

Rewards functions

claim

Claim accumulated reserve rewards for _user.

function claim(BToken _bToken, address _user, bool _asNative) external returns (uint256 amount_)
ParameterTypeDescription
_bTokenBTokenThe staked bToken
_useraddressUser claiming rewards
_asNativeboolSend wrapped native reserve as native ETH when supported

Returns:

  • amount_: reserve tokens claimed

View functions

getEarned

Get unclaimed rewards for a user in the reserve asset.

function getEarned(BToken _bToken, address _user) external view returns (uint256)
ParameterTypeDescription
_bTokenBTokenThe staked bToken
_useraddressUser to query

Returns: uint256, reserve-denominated rewards not yet claimed.

getAccumulator

Preview the current global reward accumulator and distribution state for a pool.

function getAccumulator(BToken _bToken)
  external view returns (uint256 accumulator_, uint256 newYield_, uint256 tokensPerSecond_)
ParameterTypeDescription
_bTokenBTokenPool to query

Returns:

  • accumulator_: current reward accumulator
  • newYield_: pending yield that would be distributed on sync
  • tokensPerSecond_: current streamed reward rate

getCurrentRate

Get the current annualized reward distribution rate for a staked bToken.

function getCurrentRate(BToken _bToken) external view returns (uint256)
ParameterTypeDescription
_bTokenBTokenPool to query

Returns: uint256, annualized reserve reward rate per staked bToken, scaled by the bToken decimals.


Events

event Deposit(BToken bToken, address user, uint256 amount, State.StakedAccount post);
event Withdraw(BToken bToken, address user, uint256 amount, State.StakedAccount post);
event Claim(BToken bToken, address user, uint256 amount);
event Liquidate(BToken bToken, address user, uint256 amount, State.StakedAccount post);

Errors

ErrorDescription
BStaking_StakeIsLockedAttempting to withdraw locked stake
BStaking_BTokenNotInitializedBToken pool is not initialized

Usage Example

// Stake 1000 bTokens
bToken.approve(address(bstaking), 1000e18);
bstaking.deposit(bToken, msg.sender, 1000e18);

// Check earned rewards
uint256 earned = bstaking.getEarned(bToken, msg.sender);

// Claim rewards as native ETH when the reserve supports it
uint256 claimed = bstaking.claim(bToken, msg.sender, true);

// Withdraw and claim in one tx
bstaking.withdrawAndClaim(bToken, 500e18);

ABI

[
  {
    "type": "function",
    "name": "LABEL",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "bytes32",
        "internalType": "bytes32"
      }
    ],
    "stateMutability": "pure"
  },
  {
    "type": "function",
    "name": "ROUTES",
    "inputs": [],
    "outputs": [
      {
        "name": "routes_",
        "type": "bytes4[]",
        "internalType": "bytes4[]"
      }
    ],
    "stateMutability": "pure"
  },
  {
    "type": "function",
    "name": "VERSION",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "pure"
  },
  {
    "type": "function",
    "name": "claim",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_user",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "_asNative",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "outputs": [
      {
        "name": "amount_",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "deposit",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_user",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "_amount",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "getAccumulator",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      }
    ],
    "outputs": [
      {
        "name": "accumulator_",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "newYield_",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "tokensPerSecond_",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getCurrentRate",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getEarned",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_user",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "liquidate",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_user",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "_amount",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "supportsInterface",
    "inputs": [
      {
        "name": "_interfaceId",
        "type": "bytes4",
        "internalType": "bytes4"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "pure"
  },
  {
    "type": "function",
    "name": "sync",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "withdraw",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_amount",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "withdrawAndClaim",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      },
      {
        "name": "_amount",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "withdrawMax",
    "inputs": [
      {
        "name": "_bToken",
        "type": "address",
        "internalType": "contract BToken"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "event",
    "name": "Claim",
    "inputs": [
      {
        "name": "bToken",
        "type": "address",
        "indexed": false,
        "internalType": "contract BToken"
      },
      {
        "name": "user",
        "type": "address",
        "indexed": false,
        "internalType": "address"
      },
      {
        "name": "amount",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      }
    ],
    "anonymous": false
  },
  {
    "type": "event",
    "name": "Deposit",
    "inputs": [
      {
        "name": "bToken",
        "type": "address",
        "indexed": false,
        "internalType": "contract BToken"
      },
      {
        "name": "user",
        "type": "address",
        "indexed": false,
        "internalType": "address"
      },
      {
        "name": "amount",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "post",
        "type": "tuple",
        "indexed": false,
        "internalType": "struct State.StakedAccount",
        "components": [
          {
            "name": "amount",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "locked",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "earned",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "userAccumulator",
            "type": "uint256",
            "internalType": "uint256"
          }
        ]
      }
    ],
    "anonymous": false
  },
  {
    "type": "event",
    "name": "Liquidate",
    "inputs": [
      {
        "name": "bToken",
        "type": "address",
        "indexed": false,
        "internalType": "contract BToken"
      },
      {
        "name": "user",
        "type": "address",
        "indexed": false,
        "internalType": "address"
      },
      {
        "name": "amount",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "post",
        "type": "tuple",
        "indexed": false,
        "internalType": "struct State.StakedAccount",
        "components": [
          {
            "name": "amount",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "locked",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "earned",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "userAccumulator",
            "type": "uint256",
            "internalType": "uint256"
          }
        ]
      }
    ],
    "anonymous": false
  },
  {
    "type": "event",
    "name": "Withdraw",
    "inputs": [
      {
        "name": "bToken",
        "type": "address",
        "indexed": false,
        "internalType": "contract BToken"
      },
      {
        "name": "user",
        "type": "address",
        "indexed": false,
        "internalType": "address"
      },
      {
        "name": "amount",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "post",
        "type": "tuple",
        "indexed": false,
        "internalType": "struct State.StakedAccount",
        "components": [
          {
            "name": "amount",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "locked",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "earned",
            "type": "uint128",
            "internalType": "uint128"
          },
          {
            "name": "userAccumulator",
            "type": "uint256",
            "internalType": "uint256"
          }
        ]
      }
    ],
    "anonymous": false
  },
  {
    "type": "error",
    "name": "BStaking_BTokenNotInitialized",
    "inputs": []
  },
  {
    "type": "error",
    "name": "BStaking_StakeIsLocked",
    "inputs": []
  },
  {
    "type": "error",
    "name": "Component_NotPermitted",
    "inputs": []
  },
  {
    "type": "error",
    "name": "GuardLib_InsufficientSettledReserves",
    "inputs": []
  },
  {
    "type": "error",
    "name": "GuardLib_InvalidCirculatingSupply",
    "inputs": []
  },
  {
    "type": "error",
    "name": "GuardLib_Paused",
    "inputs": []
  },
  {
    "type": "error",
    "name": "GuardLib_Reentrant",
    "inputs": []
  },
  {
    "type": "error",
    "name": "GuardLib_ReserveAccountingMismatch",
    "inputs": []
  }
]