> ## Documentation Index
> Fetch the complete documentation index at: https://docs.berachain.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Staking Pools Operator Guide

> Configure and operate a staking pool: roles, commission, reward allocation, min effective balance, and front-end.

This guide helps validators set up and manage staking pools to offer liquid staking services to their communities.

## Quick reference

### Key parameters

| Parameter                 | Range                                       | Purpose                                      |
| ------------------------- | ------------------------------------------- | -------------------------------------------- |
| Validator Commission      | 0-20%                                       | Commission on incentive token distribution   |
| Protocol Fee              | 0-20%                                       | Fee on eligible staking-pool reward growth   |
| Minimum Effective Balance | ≥ 250,000 BERA                              | Activation threshold and full exit safeguard |
| Withdrawal Delay          | 129,600 blocks (≈3 days at \~2s block time) | Time before withdrawals can be finalized     |

### Key roles

| Role                               | Controls              | Function                               |
| ---------------------------------- | --------------------- | -------------------------------------- |
| `VALIDATOR_ADMIN_ROLE`             | All other roles       | Grant/revoke operational roles         |
| `REWARDS_ALLOCATION_MANAGER_ROLE`  | Reward allocation     | Direct PoL incentives to applications  |
| `COMMISSION_MANAGER_ROLE`          | Commission rate       | Adjust validator commission (0-20%)    |
| `PROTOCOL_FEE_MANAGER_ROLE`        | Protocol fee          | Adjust protocol fee percentage (0-20%) |
| `INCENTIVE_COLLECTOR_MANAGER_ROLE` | Payout amount         | Adjust incentive collector payout      |
| `DELEGATION_MANAGER_ROLE`          | Delegation operations | Manage delegations                     |

### Essential functions

Core lifecycle and PoL reward allocation:

| Function                     | Contract      | Purpose                      |
| ---------------------------- | ------------- | ---------------------------- |
| `setMinEffectiveBalance()`   | SmartOperator | Set activation threshold     |
| `queueValCommission()`       | SmartOperator | Queue commission rate change |
| `queueRewardsAllocation()`   | SmartOperator | Queue reward allocation      |
| `setProtocolFeePercentage()` | SmartOperator | Set protocol fee rate        |

Protocol fee accrual (same percentage applies to both tracks during migration):

| Function                  | Contract      | Purpose                                                                                                                        |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `accrueEarnedWBERAFees()` | SmartOperator | Accrue protocol fees on **WBERA** balance growth — primary path after PoL Next.                                                |
| `accrueEarnedBGTFees()`   | SmartOperator | Accrue protocol fees on remaining **BGT** balance — **legacy / transitional** until BGT allowances are exhausted on your pool. |

Manual lever for compounding operator WBERA into pool assets:

| Function           | Contract    | Purpose                                                                                                       |
| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------- |
| `processRewards()` | StakingPool | Pull buffered staking rewards and any operator-held WBERA into the pool. Permissionless; callable any caller. |

Operator action is not required to make WBERA reach stakers. Compounding fires automatically inside any user `deposit()` and inside `processRewards()`; covering withdrawals from operator-side WBERA fires automatically inside `WithdrawalVault.requestWithdrawal()`. See [Automatic WBERA flows](#automatic-wbera-flows) below.

Legacy incentive surface (kept for transition; see [Deprecated BGT entry points](#deprecated-bgt-entry-points)):

| Function              | Contract      | Purpose                                                                                                                                                                 |
| --------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `claimBoostRewards()` | SmartOperator | **Legacy:** forward **BGT-era** boost incentive claims toward **`IncentiveCollector`**. Prefer WBERA-native operator flows for ongoing activity; treat as transitional. |

## Prerequisites

Before setting up a staking pool, ensure you have a fully operational Berachain validator node. You'll need at least 10,000 BERA to register the pool, though activation requires at least 250,000 BERA. See the [Validator Lifecycle](/nodes/architecture/validator-lifecycle) and [Become a Validator](/nodes/guides/become-a-validator) guides.

<Warning>
  Staking pools follow the standard Berachain validator lifecycle. After deployment, your validator
  will progress through the Deposited → Eligible states, but activation to the Active state depends
  on the ValidatorSetCap and your validator's priority relative to other validators.
</Warning>

## Validator lifecycle

Your staking pool integrates with Berachain's validator lifecycle. For details on validator states (Deposited, Eligible, Active, Exited, Withdrawn) and transitions, see the [Validator Lifecycle documentation](/nodes/architecture/validator-lifecycle).

The key consideration for staking pools is ensuring sufficient stake for activation. See [Setting Minimum Effective Balance](#setting-minimum-effective-balance) below.

## Key terms and concepts

* **Active Threshold**: The point at which your pool has sufficient stake (`totalDeposits >= minEffectiveBalance`) to activate the validator. When `activeThresholdReached()` returns `true`, your validator enters a cooldown period before activation.
* **Minimum Effective Balance (`minEffectiveBalance`)**: The minimum stake amount required for validator activation and a safeguard that triggers full exit if deposits fall below it. This must match or exceed the current consensus layer minimum (250,000 BERA when the set is not full; when the set is full, the minimum is 10,000 BERA more than the lowest active validator).
* **Withdrawal Delay**: 129,600 blocks (≈3 days at \~2s block time) that must pass after a withdrawal request before it can be finalized.
* **Cooldown Period**: After `activeThresholdReached()` becomes `true`, there is a cooldown period before the validator activates.

## Yield model

After the May 2026 PoL upgrade, per-block validator emission is a **flat fixed rate** (no boost curve).
Pools no longer differentiate on attracted BGT delegation; what you control is:

* **Validator reward allocation (cutting board)** — direct emissions to vaults you and your community care about. See [Manage Reward Allocations](/nodes/guides/manage-reward-allocations).
* **Incentives attracted to vaults you allocate to** — protocols still incentivize specific Reward Vaults; a strong allocation strategy increases incentive yield to your stakers.
* **Validator commission on incentive tokens** — capped at 20%, denominated in the WBERA-era incentive flow. See [Manage Validator Incentives Commission Rate](/nodes/guides/manage-incentives-commission).

Validator emissions accrue as \$WBERA on your `SmartOperator`. Protocol fee accrual on the WBERA track uses `accrueEarnedWBERAFees()`. The same WBERA fee update also runs automatically inside `withdrawRewards`, `pullBeraToWithdrawalVault`, and `setProtocolFeePercentage()`, so calling `accrueEarnedWBERAFees()` directly is mostly a forced-settlement / monitoring tool. `accrueEarnedBGTFees()` is a no-op once chargeable BGT is exhausted.

## Automatic WBERA flows

`SmartOperator` exposes two state-changing entry points that move WBERA out of the operator: `withdrawRewards(uint256)` and `pullBeraToWithdrawalVault(uint256)`. Both are restricted by sender — `withdrawRewards` accepts the StakingPool only; `pullBeraToWithdrawalVault` accepts the WithdrawalVault only. Operators cannot call them directly, and no operator action is required to make WBERA reach stakers.

* **Compounding into pool assets** — Any user `deposit()` and any call to `StakingPool.processRewards()` invokes `_collectRewards(...)`, which calls `SmartOperator.withdrawRewards(...)` on operator WBERA first, then drains the staking rewards vault. Operator WBERA is pulled first so `_getTotalAssets()` is correct before protocol fees mint staker shares via `mintFeeShares` during WBERA fee accrual. The unwrapped BERA lands in the pool, lifts `_getTotalAssets()`, and lifts share price for every staker.
* **Deposit ordering and fee fairness** — Inside `_submit`, the pool mints the depositor's stBERA **before** calling `_collectRewards(...)`. The depositor's shares are priced against the pre-collection NAV (which already includes pending operator WBERA via `rebaseableWberaAmount()`), so they pay a fair price for the yield about to settle. The collection that follows charges WBERA-track protocol fees and mints fee shares to the default recipient against the post-deposit NAV, so the new depositor's principal is not taxed as if it were accrued yield. `processRewards()` runs the same `_collectRewards → bufferedAssets bump → _processDeposit` sequence without minting user shares.
* **Covering withdrawals from operator liquidity** — `WithdrawalVault.requestWithdrawal()` precomputes `pulledFromOperator = min(amountInWei, availableWBERABalance)` and calls `pullBeraToWithdrawalVault(...)` on the normal partial-withdrawal branch. The execution-layer withdrawal request to the consensus layer is reduced to the uncovered remainder; if the operator covers in full, no consensus-layer request is issued and the EIP-7002 fee is refunded to the requester. Short-circuit (pool not yet at active threshold) and full-exit branches do not consume operator WBERA.
* **Full exit sweep** — Triggering a full exit sweeps any idle operator WBERA into the pool before the pool forwards its native balance to the WithdrawalVault.

For monitoring, watch `availableWBERABalance()`, `rebaseableWberaAmount()`, and `getEarnedWBERAFeeState()` on the SmartOperator. The only operator-side write you may want to invoke explicitly is `processRewards()` on the StakingPool (permissionless `whenNotPaused`) — it forces a compounding cycle without waiting for the next user deposit.

## Configuration

### Commission rates

You can set commission rates within 0-20%. Commission applies to the distribution of incentive tokens from Proof of Liquidity rewards. For step-by-step instructions, see [Manage Validator Incentives Commission Rate](/nodes/guides/manage-incentives-commission).

### Reward allocations

Direct PoL incentives to specific applications. For instructions, see [Managing Validator Reward Allocations](/nodes/guides/manage-reward-allocations).

### Setting minimum effective balance

The `minEffectiveBalance` parameter is critical for validator activation. The consensus layer enforces a base minimum of **250,000 BERA**. When the validator set is full (69 validators), the minimum required increases in increments of **10,000 BERA**. Set `minEffectiveBalance` to match the current consensus layer requirement. You can check the current lowest active stake on [Berachain Hub](https://hub.berachain.com/boost/).

## Routine operations

* **Monitor pool status**: Use `isActive()`, `totalAssets()`, `bufferedAssets()`, `activeThresholdReached()` on your StakingPool and SmartOperator. For operator-side liquidity, also watch **`availableWBERABalance()`**, **`rebaseableWberaAmount()`**, and **`getEarnedWBERAFeeState()`** on SmartOperator. See [Automatic WBERA flows](#automatic-wbera-flows) for how this liquidity moves.
* **Delegation operations**: Manage delegations as needed. **PoL Next:** validator emissions accrue as **\$WBERA** on **`SmartOperator`**. Accrue protocol fees on the WBERA track with **`accrueEarnedWBERAFees()`**; use **`accrueEarnedBGTFees()`** only while your pool still has chargeable **BGT** on the operator. **`claimBoostRewards()`** is a **legacy** entry point for the **BGT** incentive-distributor surface — confirm it still matches your deployed implementation before relying on it for new workflows.
* **Emission token context**: PoL Reward Vault emissions are distributed in **\$WBERA**.
* **Protocol fee**: Set via `setProtocolFeePercentage()` (up to 20%). The fee setter charges both tracks before applying the new rate. Call `accrueEarnedWBERAFees()` to force WBERA-track settlement; call `accrueEarnedBGTFees()` if you want to settle the legacy BGT track explicitly.

## Deprecated BGT entry points

The May 2026 PoL upgrade deprecates the BGT-era surface on `SmartOperator`. The following entry points stay callable for transition (all `whenNotFullyExited` where applicable) but become inert once chargeable BGT is exhausted on your operator:

* `queueBoost()`, `activateBoost()`, `queueDropBoost(uint128)` — boost-management calls; per-block emission no longer scales with delegation, so these have no effect on yield.
* `claimBgtStakerReward()` — BGT-staker reward forwarder.
* `claimBoostRewards(IBGTIncentiveDistributor.Claim[], address[])` — BGT-era boost incentive distributor forwarder.
* `accrueEarnedBGTFees()` — fee accrual on the BGT track; no-op when chargeable BGT is zero.

Berachain recommends winding down BGT positions held on your `SmartOperator` (unboost, drop-boost, redeem) using the same calls during the transition window.

## Withdrawal system

The shared **`WithdrawalVault`** is a per-chain singleton (a single proxy + implementation) that finalizes withdrawal requests for every staking pool. Three sources of liquidity can satisfy a request:

* **Short-circuit** — pool not yet at the active threshold. Liquidity comes only from the pool's on-chain **`bufferedAssets`**. BeaconKit honors EIP-7002 withdrawal requests only for **active** validators; a validator that has not activated cannot withdraw via the consensus layer, so this branch never issues a CL request. If the buffer cannot cover the request, the transaction reverts rather than falling through into post-threshold or full-exit logic.
* **Standard consensus-layer withdrawal** — execution-layer request to the validator's pubkey.
* **Operator-side WBERA cover** — at request time, the vault pulls from **`availableWBERABalance()`** on your pool's `SmartOperator`, unwraps to native BERA, and applies it to the request. Coverage may be **full** (the consensus-layer request is skipped and the EIP-7002 fee is refunded), **partial** (the remainder still exits via the consensus layer), or **none** when operator liquidity is empty.

**Post-exit pools:** Once the validator has fully exited (`isFullyExited`), withdrawal handling skips the pre-threshold default-recipient gate and the post-threshold activation cooldown. BERA is already in the `WithdrawalVault`; requests proceed without re-entering activation-era guards.

**Finalization delay:** `finalizeWithdrawalRequest` / `finalizeWithdrawalRequests` enforce `block.number >= requestBlock + WITHDRAWAL_REQUEST_FINALIZATION_BLOCK_DELAY` (currently **129,600** blocks, ≈3 days at \~2s block time) for every request. The cover source affects only **where the BERA comes from**; it does not shorten the cooldown. The pull from operator WBERA happens at **request** time, so covered BERA sits in the vault until the cooldown elapses.

**Retrying a full exit (`retryFullExit`):** When a full exit is triggered, the pool marks the validator fully exited and the vault submits an EIP-7002 full-exit request (withdrawal amount **0**). If that consensus-layer request fails or is dropped, anyone can call **`retryFullExit(pubkey, maxFeeToPay)`** on the shared `WithdrawalVault` to re-submit — permissionless, sending the EIP-7002 **withdrawal fee** with the call (`maxFeeToPay` is the most you are willing to pay). The validator must already be marked fully exited (`NotFullyExited` otherwise). The call reverts with **`PendingWithdrawalInFlight`** if a partial withdrawal was requested within the last **49,153** blocks (`WITHDRAWAL_FLIGHT_BLOCK_DELAY`), giving in-flight partial exits time to settle before retrying a full exit. Success emits **`FullExitRequestRetried`**. This path is for recovering a stuck post-exit CL sweep; normal staker withdrawal requests do not use it.

## Building your front-end

Your front-end should:

* Display withdrawal status and when each request can be finalized (use `getWithdrawalRequest(requestId)` and `requestBlock + 129600`).
* Support batch finalization with `finalizeWithdrawalRequests([...])`.
* Show staker balance, share price, and total rewards (e.g. via `previewRedeem(shares)`).

Berachain provides a React-based example template in the [guides repository](https://github.com/berachain/guides/tree/main/apps/staking-pools/frontend). Use `generate-frontend-config.sh` from `install-helpers` to generate `config.json` from your environment.

## Delegation

If you have received a delegation from the Berachain Foundation, see the [Delegation Guide](/nodes/staking-pools/delegators) and the [DelegationHandler](https://github.com/berachain/guides/tree/main/apps/staking-pools) contract reference.

## More information

* [Staking Pools Overview](/nodes/staking-pools/overview)
* [Smart Contract Reference](/nodes/staking-pools/contracts)
* [Install-helpers README](https://github.com/berachain/guides/blob/main/apps/staking-pools/install-helpers/README.md)
