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:
- Share of total stake: staked amount over total staked
- Time staked: rewards accrue over time with the position
- 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| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The bToken to stake |
_user | address | User receiving the stake position |
_amount | uint256 | Amount of bTokens to stake |
withdraw
Withdraw unlocked staked bTokens for msg.sender.
function withdraw(BToken _bToken, uint256 _amount) external| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The staked bToken |
_amount | uint256 | Amount to withdraw |
withdrawMax
Withdraw all currently unlocked bTokens for msg.sender.
function withdrawMax(BToken _bToken) external| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The staked bToken |
withdrawAndClaim
Withdraw _amount of unlocked staked bTokens and claim pending rewards in one call.
function withdrawAndClaim(BToken _bToken, uint256 _amount) external| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The staked bToken |
_amount | uint256 | bToken amount to withdraw |
Rewards functions
claim
Claim accumulated reserve rewards for _user.
function claim(BToken _bToken, address _user, bool _asNative) external returns (uint256 amount_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The staked bToken |
_user | address | User claiming rewards |
_asNative | bool | Send 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)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The staked bToken |
_user | address | User 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_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | Pool to query |
Returns:
accumulator_: current reward accumulatornewYield_: pending yield that would be distributed on synctokensPerSecond_: current streamed reward rate
getCurrentRate
Get the current annualized reward distribution rate for a staked bToken.
function getCurrentRate(BToken _bToken) external view returns (uint256)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | Pool 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
| Error | Description |
|---|---|
BStaking_StakeIsLocked | Attempting to withdraw locked stake |
BStaking_BTokenNotInitialized | BToken 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": []
}
]Related
- Staking Guide : How to stake
- BLens Contract : View staking state
BSwap
BSwap is the Mercury AMM for bTokens on Ethereum, with n=2 power-law curve, exact in/out trades, quotes, fees, events, errors, and full JSON ABI for viem, ethers, and integrations.
BCredit
BCredit is Mercury credit on Ethereum, with 0% borrow, leverage, deleverage, repay, BLV-backed solvency, preview functions, events, errors, and JSON ABI for builders.