diff --git a/README.md b/README.md index a258d16..21c5724 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ We welcome contributions from the community. Whether you're fixing a typo, clari - **Build**: developer guides, integrations, and contract reference - **Nodes**: node architecture, setup, operations, staking pools, and Beacon Kit reference -Content is in MDX. `docs.json` defines navigation and branding. [STRUCTURE.md](STRUCTURE.md) defines content placement. +Content is in MDX. `docs.json` defines navigation and branding. `STRUCTURE.md` defines content placement. --- diff --git a/docs.json b/docs.json index 55f4e5b..995941f 100644 --- a/docs.json +++ b/docs.json @@ -298,7 +298,6 @@ "pages": [ "nodes/staking-pools/installation", "nodes/staking-pools/operators", - "nodes/staking-pools/delegators", "nodes/staking-pools/contracts" ] } @@ -440,7 +439,7 @@ }, { "source": "/cn/validators/staking-pools/delegators", - "destination": "/validators/staking-pools/delegators" + "destination": "/validators/staking-pools/installation" }, { "source": "/cn/validators/staking-pools/contracts", @@ -464,7 +463,7 @@ }, { "source": "/ko/validators/staking-pools/delegators", - "destination": "/validators/staking-pools/delegators" + "destination": "/validators/staking-pools/installation" }, { "source": "/ko/validators/staking-pools/contracts", @@ -488,12 +487,17 @@ }, { "source": "/vi/validators/staking-pools/delegators", - "destination": "/validators/staking-pools/delegators" + "destination": "/validators/staking-pools/installation" }, { "source": "/vi/validators/staking-pools/contracts", "destination": "/validators/staking-pools/contracts" }, + { + "source": "/nodes/staking-pools/delegators", + "destination": "/nodes/staking-pools/installation", + "permanent": true + }, { "source": "/validators/:slug*", "destination": "/nodes/:slug*", diff --git a/nodes/staking-pools/contracts.mdx b/nodes/staking-pools/contracts.mdx index cf07aa7..932b600 100644 --- a/nodes/staking-pools/contracts.mdx +++ b/nodes/staking-pools/contracts.mdx @@ -1,32 +1,30 @@ --- -title: "Staking Pool Contracts" -description: "Addresses and ABIs for StakingPoolContractsFactory, DelegationHandlerFactory, WithdrawalVault, and per-pool proxies (StakingPool, SmartOperator, etc.)." +title: "Look up staking pool contract addresses" +description: "Singleton addresses and ABIs, plus the per-pool proxies StakingPoolContractsFactory deploys." --- import StakingPoolSingletonsTable from "/snippets/contracts/generated/staking-pools-singletons-table.mdx"; -This reference provides contract addresses and links to detailed documentation for each contract in the staking pools system. For an overview of how the contracts work together, see the [Staking Pools Overview](/nodes/staking-pools/overview). +This page lists staking-pool contract addresses and ABI links. The [Staking pools overview](/nodes/staking-pools/overview) explains how the contracts fit together. -## Contract addresses +## Singleton contracts -### Singleton contracts - -Singleton contracts are deployed once and shared across all staking pools. The **StakingPoolContractsFactory** is the entry point for deploying a staking pool: you call it to create and register your pool's contracts. The **DelegationHandlerFactory** deploys per-validator delegation handler proxies when using foundation delegation. The other singletons below are shared infrastructure. +These contracts are deployed once and shared by every pool: -### Deployed contracts (per pool) +Call `StakingPoolContractsFactory` to create and register a pool. Call `DelegationHandlerFactory` to deploy a per-validator handler proxy for Foundation delegation. The other rows are shared infrastructure. -When you deploy a staking pool through the StakingPoolContractsFactory, the factory creates proxy contracts for your validator. These proxy contracts are what you and your stakers interact with directly. Each validator receives unique proxy addresses for these contracts when deploying their staking pool. +## Per-pool proxy contracts -The factory returns these proxy addresses when you call `deployStakingPoolContracts`. Store these addresses for your operations and provide the StakingPool address to your stakers for deposits. +`deployStakingPoolContracts` returns proxy addresses for your validator. You and your stakers call those proxies. Store the addresses. Give stakers the StakingPool address for deposits. -**Proxy contracts deployed with your pool:** +Proxy contracts for each pool: -- **StakingPool**: Main staking functionality and staker interactions. This is the contract address your stakers use to deposit BERA and receive stBERA shares. -- **SmartOperator**: Validator operations and Proof of Liquidity integration. -- **IncentiveCollector**: Incentive token collection and conversion. Handles the incentive auction mechanism where accumulated tokens can be claimed. -- **StakingRewardsVault**: Reward collection and automatic reinvestment. Automatically compounds rewards from the consensus layer. -- **DelegationHandler**: Delegation handling for capital providers. Only deployed if you're using delegated funds from the Berachain Foundation. +- **StakingPool**: deposits, shares, and staker interactions. Stakers deposit BERA here and receive stBERA. +- **SmartOperator**: validator operations and Proof of Liquidity integration. +- **IncentiveCollector**: incentive token collection, conversion, and the incentive auction. +- **StakingRewardsVault**: consensus-layer reward collection and compounding. +- **DelegationHandler**: Foundation-delegated capital. Deployed only on the delegated path. -For detailed technical documentation of each contract's functions and behavior, see the [Berachain guides repository](https://github.com/berachain/guides/tree/main/apps/staking-pools) and the [install-helpers README](https://github.com/berachain/guides/blob/main/apps/staking-pools/install-helpers/README.md). +ABI JSON for each singleton is in the table above. For install and operator flows, see [Install a staking pool](/nodes/staking-pools/installation) and the [Operator guide](/nodes/staking-pools/operators). diff --git a/nodes/staking-pools/delegators.mdx b/nodes/staking-pools/delegators.mdx deleted file mode 100644 index 13e932a..0000000 --- a/nodes/staking-pools/delegators.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: "Delegation Guide" -description: "Use Foundation-delegated capital to run a staking pool: delegated create, activate, deposit, and withdraw yield." ---- - -This guide shows validator operators how to use delegated capital to stand up and run a staking pool. It builds on the Installation guide and reuses the same helper scripts. It does not cover delegator actions; coordinate with your capital provider as needed. - -See [Installation](/nodes/staking-pools/installation) first. At minimum, set up `env.sh` in `install-helpers/`. - - - All helper scripts write `cast` commands to files; review and run them yourself. Transactions are - never sent automatically. Signing defaults to Ledger; set `PRIVATE_KEY` in `env.sh` if you prefer - a local key. - - -## Assumptions - -- You completed the validator Installation steps (env configured, node synced). -- The Berachain Foundation has prepared a DelegationHandler and delegated funds for your validator pubkey. - -## 1. Check readiness - -Confirm the chain, validator pubkey, and whether a delegated pool/handler is detected: - -```bash -./status.sh -``` - -If a handler exists, the script displays delegated amounts and whether a pool already exists for your pubkey. - -## 2. Create the pool with delegated funds (first 10,000 BERA) - -If the pool is not yet created, use the delegated creation script. It consumes the first 10,000 BERA from the handler to register the validator and writes a ready-to-run command file. This step is the delegated equivalent of the self-funded flow's `register.sh` (it performs the 10,000 BERA deposit and deploys the pool contracts). - -```bash -./delegated-create-pool.sh -``` - -This will create a script with deployment commands. Review it. Then run it to submit the transaction, then wait for confirmation. - -## 3. Wait for validator registration - -After deploying the contracts, wait for your validator to be registered on the beacon chain. You can check registration status with: - -```bash -./status.sh -``` - -The validator must appear on the beacon chain before you can activate the pool. - -## 4. Activate the pool - -Activation mirrors the Installation flow. Once the validator is recognised as registered on the beacon chain, run `activate.sh`: - -```bash -./activate.sh -``` - -`activate.sh` is a permissionless call keyed on your validator pubkey and no longer takes `--sr` or `--op`. It preflights the activation locally (pool deployed, pool not already active, operator and withdrawal-credentials match, proofs verify against a single pinned slot) and writes `generated/activation-command.sh` for you to review and execute. Proofs are contract-checked against `MAX_TIMESTAMP_AGE` = 10 minutes; if you delay broadcasting beyond that window, re-run `activate.sh` to regenerate. - -## 5. Deposit remaining delegated funds - -After activation, deposit the remaining delegated funds to reach your target balance (for example, 250,000 BERA on Bepolia). The script writes a command file for you to execute. - -```bash -./delegated-deposit.sh --amount 240000 -``` - -## 6. Verify status - -```bash -./status.sh -``` - -You should see contract addresses, the operator match on the beacon deposit contract, and the pool marked ACTIVE. The script also reports delegated amounts when a handler is present. - -## 7. Withdraw yield (operator) - -Operators can withdraw earned yield independently of principal. The helper script writes two commands (request, then complete after cooldown): - -```bash -./delegated-withdraw-yield.sh --pubkey 0xYOUR_VALIDATOR_PUBKEY -``` - -Follow the prompts to execute the generated request and completion scripts after the cooldown. - -Yield withdrawal redeems only the **share excess** over the delegated principal still on the handler: the `DelegationHandler` computes `lockedShares = previewWithdraw(delegatedAmountUsed)` and excludes those shares from the redeemable amount. Any growth above the locked principal — protocol-fee shares accrued to the default recipient, reward-vault yield, operator-side WBERA — is freely redeemable; the delegated principal itself is not. - -Principal withdrawals are controlled by the delegator and are out of scope here. Once you have attracted additional depositors, the foundation can redeem its stake without causing your validator to exit. - - - If you are self-funded, use `stake.sh` from the [Installation - guide](/nodes/staking-pools/installation) instead of the delegated deposit flow. - - -## Where to next - -- [Contract reference](/nodes/staking-pools/contracts) explains what you've deployed -- [Operator Guide](/nodes/staking-pools/operators) explains what a staking pool operator can do diff --git a/nodes/staking-pools/installation.mdx b/nodes/staking-pools/installation.mdx index 9b92337..a96e604 100644 --- a/nodes/staking-pools/installation.mdx +++ b/nodes/staking-pools/installation.mdx @@ -1,146 +1,72 @@ --- -title: "Staking Pool Installation" -description: "Install and activate a staking pool with helper scripts: register, activate, set min effective balance, and optional stake." +title: "Install a staking pool" +description: "Deploy and activate a staking pool from a remote machine with install.sh." --- -This guide walks validator operators through installing and activating a staking pool using the helper scripts. +`install.sh` deploys and activates one staking pool from `guides/apps/staking-pools/install-helpers/`. You configure the environment, run the script, and execute the commands it asks you to. The script uses Foundation-delegated funds when a DelegationHandler has been provisioned for your validator. Otherwise it spends **10,000 BERA** plus gas from your funding wallet. -## What you'll use +## What you need before you run install.sh -The helper scripts are available through GitHub: +You need a synced validator, helper tools, and live endpoints: -```bash -git clone https://github.com/berachain/guides/ -cd guides/apps/staking-pools -ls -F -# frontend/ install-helpers/ -``` - -There are many useful scripts under `install-helpers/` which wrap multi-step operations into safe, review-first commands: - -- **register.sh**: Deploys (registers) staking pool contracts and generates the deployment transaction -- **activate.sh**: Activates a deployed pool using validator proofs from the beacon chain -- **status.sh**: Verifies deployment, registration, and activation status -- **stake.sh**: Generates a staking transaction to add BERA to your pool - - - All scripts write ready-to-run `cast` commands to files for you to review and execute. They do not - send transactions without your confirmation. By default, scripts use Ledger for signing; set - `PRIVATE_KEY` in `env.sh` if you prefer a local key. - - -## Requirements - -- beacond (validator client) running and synced with your validator keys **backed up somewhere safe** -- Foundry `cast` ([getfoundry.sh](https://getfoundry.sh/)) -- `jq`, `bc`, `curl` -- Ledger hardware wallet (default) or a private key set via `PRIVATE_KEY` -- Funds: at least 10,000 BERA for the initial deposit; additional stake as desired - -## 1. Configure environment - -In `install-helpers/`: - -```bash -cp env.sh.template env.sh -# Edit env.sh and set at minimum: -# BEACOND_HOME="/path/to/your/beacond/home" -# NODE_API_ADDRESS="127.0.0.1:3500" # If not auto-detected from app.toml -# Optionally set: -# PRIVATE_KEY="0x..." # Defaults to Ledger if unset -``` - -Ensure the beacon node API is enabled in your `app.toml` (`[beacon-kit.node-api]`) or provide `NODE_API_ADDRESS` in `env.sh`. The scripts will auto-detect when possible and verify connectivity before proceeding. - -## 2. Register (deploy contracts) - -Run `register.sh` with your addresses to deploy the staking pool contracts: - -```bash -./register.sh --sr 0xSHARES_RECIPIENT --op 0xOPERATOR -``` - -1. The chain (mainnet or Bepolia) is auto-detected from your beacond configuration. -2. The initial stake is 10,000 BERA (fixed by the consensus layer). The script writes `deployment-command.sh` with this deposit. Review it. Simulate it if you want. Then run it. This should dump a successful transaction receipt. -3. The script also predicts and shows your staking pool contract addresses ahead of time. - -## 3. Wait for validator registration +- A synced Berachain validator +- `bash`, [Foundry](https://book.getfoundry.sh/) (`cast`), `jq`, and `curl` +- Reachable execution-layer JSON-RPC and consensus-layer Node API endpoints. [Enable the Node API](https://docs.berachain.com/nodes/beaconkit/configuration#node-api-beacon-kit-node-api). The Node API can run on any node; it doesn't have to be on the validator. -After deploying the contracts, wait for your validator to be registered on the beacon chain. You can check registration status with: +You also need one funding path: -```bash -./status.sh -``` +- Self-funded: at least **10,000 BERA** plus gas in the funding wallet +- Delegated: a DelegationHandler already formed and funded for your validator, plus gas for activation -The validator must appear on the beacon chain before you can activate the pool. +The Berachain Foundation forms the DelegationHandler when they issue a delegation. That setup is internal; operators run `install.sh` once the handler exists. -## 4. Activate the pool +## Clone install-helpers -Once your validator is registered, run `activate.sh` to activate the pool: +Clone the guides repo and enter the helper directory: ```bash -./activate.sh +git clone https://github.com/berachain/guides/ +cd guides/apps/staking-pools/install-helpers ``` -Activation is a permissionless on-chain call keyed by your validator pubkey, so `activate.sh` no longer takes `--sr` or `--op`; the pool's shares recipient and operator are already baked in from `register.sh`. The script: - -1. Verifies the pool contract is deployed and not already active (`isActive()`). -2. Confirms `BeaconDeposit.getOperator(pubkey)` matches the pool's SmartOperator and that the validator's withdrawal credentials point at the pool's WithdrawalVault. -3. Pins the beacon-chain head slot, fetches validator pubkey, withdrawal-credentials, and balance proofs at that single slot, and preflights `activateStakingPool()` locally so a bad proof or stale timestamp surfaces before you broadcast. -4. Writes `generated/activation-command.sh` for you to review and execute. - -Proofs include a timestamp enforced by the contract (`MAX_TIMESTAMP_AGE` = 10 minutes). The generated script also hard-expires after that window; if you hit it, re-run `activate.sh` to regenerate. +## Set environment variables -## 5. Verify installation - -Use `status.sh` to check deployment, registration, and activation: +Copy `env.sh.template` to `env.sh` in that directory, then edit the copy. `install.sh` sources `env.sh` when the file is present. ```bash -./status.sh +cp env.sh.template env.sh ``` -You should see the SmartOperator, StakingPool, StakingRewardsVault, and IncentiveCollector addresses, confirmation that the beacon deposit operator matches your SmartOperator, the pool's active status, and various telemetry. +| Variable | Purpose | +| ------------------ | -------------------------------------------------------------------------------------------------- | +| `EL_RPC_URL` | Execution-layer JSON-RPC. Default: Bepolia public RPC. Network is read from `eth_chainId`. | +| `CL_NODE_API_URL` | Beacon Kit Node API base URL. Default: `http://127.0.0.1:3500`. | +| `PRIVATE_KEY` | Signs `cast send` on this host when set. | +| `VALIDATOR_PUBKEY` | Validator pubkey default. | +| `FUNDING_ADDRESS` | Funding wallet on the self-funded path. Ignored when `PRIVATE_KEY` is set. | +| `OPERATOR_ADDRESS` | Operator on the self-funded path. | +| `SHARES_RECIPIENT` | Shares recipient on the self-funded path. | -## 6. Set minimum effective balance +## Run install.sh - - The `minEffectiveBalance` parameter determines when your staking pool activates its validator on - the consensus layer. If you don't set this value correctly, your pool may accumulate deposits - without ever activating. - - -Set the value using your SmartOperator contract: +Use `./install.sh --help` for usage. ```bash -cast send $SMART_OPERATOR_ADDRESS \ - "setMinEffectiveBalance(uint256)" $CALCULATED_MIN_STAKE \ - --ledger # or --private-key $PRIVATE_KEY +cp env.sh.template env.sh # optional; defaults apply without this +./install.sh ``` -Replace `$SMART_OPERATOR_ADDRESS` with your SmartOperator address and `$CALCULATED_MIN_STAKE` with the calculated minimum stake amount in wei (multiply BERA amount by 10^18). - -For details on why this matters, how to determine the correct value, and how the consensus layer minimum works, see the [Setting Minimum Effective Balance](/nodes/staking-pools/operators#setting-minimum-effective-balance) section in the operator guide. +If a DelegationHandler with delegated funds exists for your validator's pubkey, the script uses the delegated path. Otherwise it uses the self-funded path. -## 7. (Optional) Stake additional BERA +The script will walk you through obtaining the necessary information, verifying the signatures, and activating the validator. -Add stake to your pool and send stBERA to a receiver address: +Upon completion, receipts are written to `staking-pool-receipts.jsonl`. -```bash -# With BEACOND_HOME configured (pool auto-detected): -./stake.sh --amount 100 --receiver 0xRECEIVER - -# Or specify an explicit pool address: -./stake.sh --amount 100 --receiver 0xRECEIVER --staking-pool 0xPOOL -``` - -The script writes `stake-command.sh`. Review and execute the command to submit your stake. - -## Troubleshooting (quick) +## What's next -- **Node API not reachable**: Enable `[beacon-kit.node-api]` and confirm the address/port; or set `NODE_API_ADDRESS` in `env.sh`. The script will examine your files and tell you how to activate the API if it isn't enabled yet. -- **Missing tools**: Install Foundry (`cast`), `jq`, `bc`, and `curl` and ensure they are on your PATH. +The [Operator guide](/nodes/staking-pools/operators) covers day-two work. The [example frontend](https://github.com/berachain/guides/tree/main/apps/staking-pools/frontend) is a sample UI for end users. -## What's next +Continue with: -- [Contract reference](/nodes/staking-pools/contracts) explains what you've deployed -- [Delegation guide](/nodes/staking-pools/delegators) explains how to receive a Foundation delegation, which is very similar to this flow +- [Contract reference](/nodes/staking-pools/contracts) +- [Operator guide](/nodes/staking-pools/operators) diff --git a/nodes/staking-pools/operators.mdx b/nodes/staking-pools/operators.mdx index 0ebed65..91a184b 100644 --- a/nodes/staking-pools/operators.mdx +++ b/nodes/staking-pools/operators.mdx @@ -1,171 +1,98 @@ --- -title: "Staking Pools Operator Guide" -description: "Configure and operate a staking pool: roles, commission, reward allocation, min effective balance, and front-end." +title: "Operate a staking pool" +description: "After install.sh: queue commission and allocation on SmartOperator, set min effective balance, then monitor WBERA and withdrawals." --- -This guide helps validators set up and manage staking pools to offer liquid staking services to their communities. +After [Install a staking pool](/nodes/staking-pools/installation) you have a pool address. Day-two writes go through that pool's `SmartOperator`. BeraChef treats `SmartOperator` as the validator operator (`beaconDepositContract.getOperator`), so you do not call BeraChef with an EOA the way [Manage Incentives Commission](/nodes/guides/manage-incentives-commission) describes for a normal validator. -## Quick reference +## Set commission -### Key parameters +`COMMISSION_MANAGER_ROLE` calls `SmartOperator.queueValCommission(uint96 commission)`. That forwards to `BeraChef.queueValCommission(pubkey, commission)`. BeraChef rejects anything above `MAX_COMMISSION_RATE` (2000 bps, 20%). -| 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 | +The queue is not live yet. After `commissionChangeDelay` blocks, anyone calls `BeraChef.activateQueuedValCommission(pubkey)`. `SmartOperator` does not wrap that activate. -### Key roles +## Direct reward allocation -| 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 | +`REWARDS_ALLOCATION_MANAGER_ROLE` calls `SmartOperator.queueRewardsAllocation(startBlock, weights)`, which forwards to `BeraChef.queueNewRewardAllocation`. `startBlock` must be at least `block.number + rewardAllocationBlockDelay`. BeraChef only accepts the call from the pubkey's reward allocator, or from the operator if none is set. `VALIDATOR_ADMIN_ROLE` can set the allocator with `SmartOperator.setRewardAllocator`. -### Essential functions +The Distributor, not you, calls `BeraChef.activateReadyQueuedRewardAllocation`. Inactivity and fallback rules live on BeraChef; see [Manage Reward Allocations](/nodes/guides/manage-reward-allocations) for the current delay and inactivity span. -Core lifecycle and PoL reward allocation: +## Set the activation threshold -| 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 | +`VALIDATOR_ADMIN_ROLE` calls `SmartOperator.setMinEffectiveBalance`, which calls `StakingPool.setMinEffectiveBalance`. The pool reverts `InvalidMinEffectiveBalance` unless the value is at least `MIN_EFFECTIVE_BALANCE` (250,000 BERA) and strictly below `MAX_EFFECTIVE_BALANCE` (10,000,000 BERA). If you never set it, `minEffectiveBalance()` returns 250,000 BERA. -Protocol fee accrual (same percentage applies to both tracks during migration): +When `totalDeposits + bufferedAssets` first reaches that floor, `StakingPool` sets `activeThresholdReached` and records `_validatorActivationBlock`. -| 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. | +A later withdrawal whose consensus-layer portion would leave `totalDeposits` below `minEffectiveBalance()` triggers a full exit (`_triggerFullExit`). -Manual lever for compounding operator WBERA into pool assets: +## Set the protocol fee -| Function | Contract | Purpose | -| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------- | -| `processRewards()` | StakingPool | Pull buffered staking rewards and any operator-held WBERA into the pool. Permissionless; callable any caller. | +`PROTOCOL_FEE_MANAGER_ROLE` calls `SmartOperator.setProtocolFeePercentage`. The cap is `MAX_PROTOCOL_FEE` (2000 bps, 20%). The setter runs BGT and WBERA fee accrual, then stores the new rate. -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. - - - 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. - - -## 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. +`accrueEarnedWBERAFees` and `accrueEarnedBGTFees` are public, `whenNotFullyExited`, and have no role. Accrual also runs inside `withdrawRewards`, `pullBeraToWithdrawalVault`, `notifyWithdrawalRequest`, `fullExitQueueDropBoost`, and `setProtocolFeePercentage`. ## 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. +You cannot call the two functions that move WBERA off `SmartOperator`: -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. +- `withdrawRewards(amount)` reverts unless `msg.sender` is `StakingPool`. It unwraps WBERA and calls `StakingPool.receiveRewards`. +- `pullBeraToWithdrawalVault(amount)` reverts unless `msg.sender` is `WithdrawalVault`. It unwraps WBERA and sends BERA to the vault. -## Configuration +What the pool and vault do: -### Commission rates +- `StakingPool.submit` (and `receive()`) and `processRewards` call `_collectRewards`, which pulls WBERA via `withdrawRewards` when the deposit math includes `wberaToCollect`, then pulls BERA from `StakingRewardsVault`. +- `processRewards` is `whenNotPaused` and has no role. It compounds without a user deposit. +- `WithdrawalVault._withdraw` reads `availableWBERABalance()`, floors that cover to 1 gwei, and passes it into `notifyWithdrawalRequest`. The pool applies that cover only on the normal post-threshold partial path. Short-circuit and full-exit zero the cover and do not call `pullBeraToWithdrawalVault`. Full cover (remaining CL amount 0) refunds `msg.value`. Partial cover requests only the remainder from the consensus layer. +- `_triggerFullExit` calls `fullExitQueueDropBoost`, then `_collectRewards` for the whole rewards-vault balance and `availableWBERABalance()`, then sends the pool's native balance to `WithdrawalVault`. -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. +Watch `StakingPool.isActive` (factory `activate` succeeded), `activeThresholdReached`, `totalDeposits`, `bufferedAssets`, and on `SmartOperator`: `availableWBERABalance()`, `rebaseableWberaAmount()`, `getEarnedWBERAFeeState()`. ## 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: +Stakers call `WithdrawalVault.requestWithdrawal` or `requestRedeem`. The vault mints a non-transferable NFT and stores `requestBlock`. -- **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. +Liquidity: -**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. +- **Short-circuit** (`!activeThresholdReached`): BERA comes only from `bufferedAssets`. If the buffer is short, `notifyWithdrawalRequest` reverts `WithdrawalNotAllowed`. No EIP-7002 request; the vault refunds the fee. +- **Post-threshold**: `notifyWithdrawalRequest` reverts `WithdrawalNotAllowed` until `block.number >= _validatorActivationBlock + ENABLE_WITHDRAWAL_COOLDOWN_BLOCKS` (129,600). After that, uncovered amount goes to the consensus layer; operator WBERA may cover as above. +- **Fully exited**: `isFullyExited` on the pool, or `_isFullyExited[pubkey]` on the vault. BERA is already in the vault. No new CL request; the fee is refunded. -**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. +`finalizeWithdrawalRequest` / `finalizeWithdrawalRequests` revert `InvalidSender` unless `msg.sender` is `request.user`, and `RequestNotReady` until `requestBlock + WITHDRAWAL_REQUEST_FINALIZATION_BLOCK_DELAY` (129,600). Cover does not shorten that delay. -**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. +`retryFullExit(pubkey, maxFeeToPay)` is permissionless and payable. It reverts `NotFullyExited` unless the vault has marked the pubkey fully exited, and `PendingWithdrawalInFlight` if a partial withdrawal was requested in the last `WITHDRAWAL_FLIGHT_BLOCK_DELAY` (49,153) blocks. It re-submits an EIP-7002 full exit (amount 0). Staker requests do not use this path. ## 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)`). +Show finalize time from `getWithdrawalRequest(requestId)` (`requestBlock + 129600`). Only `request.user` can finalize. Use `previewRedeem(shares)` on the pool for share price. Batch with `finalizeWithdrawalRequests`. -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. +Copy the React example in the [guides repository](https://github.com/berachain/guides/tree/main/apps/staking-pools/frontend). Fill `config.example.json` with the pool address and validator pubkey from `install.sh` or factory `getCoreContracts`. -## 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 +## Deprecated BGT entry points -- [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) +These stay on `SmartOperator` with `@deprecated` in the interface. They do not wrap a staking-pool-specific yield path: + +| Call | Who | +| --- | --- | +| `queueBoost()` | `BGT_MANAGER_ROLE`, `whenNotFullyExited` | +| `queueDropBoost(uint128)` | `BGT_MANAGER_ROLE` | +| `redeemBGT(uint256)` | `BGT_MANAGER_ROLE`, `whenNotFullyExited` | +| `activateBoost()` | no role | +| `dropBoost()` | no role | +| `claimBgtStakerReward()` | no role | +| `claimBoostRewards(...)` | no role | +| `accrueEarnedBGTFees()` | no role, `whenNotFullyExited` | + +## Roles + +`DEFAULT_ADMIN_ROLE` is governance on initialize. `VALIDATOR_ADMIN_ROLE` is the role-admin for the rest: + +| Role | What it can call | +| --- | --- | +| `VALIDATOR_ADMIN_ROLE` | `setMinEffectiveBalance`, `setRewardAllocator` | +| `COMMISSION_MANAGER_ROLE` | `queueValCommission` | +| `REWARDS_ALLOCATION_MANAGER_ROLE` | `queueRewardsAllocation` | +| `PROTOCOL_FEE_MANAGER_ROLE` | `setProtocolFeePercentage` | +| `INCENTIVE_COLLECTOR_MANAGER_ROLE` | `queueIncentiveCollectorPayoutAmountChange` | +| `BGT_MANAGER_ROLE` | `queueBoost`, `queueDropBoost`, `redeemBGT` | + +Addresses and ABIs: [Look up staking pool contract addresses](/nodes/staking-pools/contracts). diff --git a/nodes/staking-pools/overview.mdx b/nodes/staking-pools/overview.mdx index f8b8ede..99d314e 100644 --- a/nodes/staking-pools/overview.mdx +++ b/nodes/staking-pools/overview.mdx @@ -1,84 +1,76 @@ --- -title: "Staking Pools Overview" -description: "Validator-operated liquid staking: stBERA, contract architecture, security, staker experience, and PoL integration." +title: "What staking pools do" +description: "Validator-operated liquid staking: stBERA, contract layout, staker flow, and Proof of Liquidity." --- -Staking Pools enable validators to offer liquid staking services to their communities. As a validator, you can build and monetize your own community of stakers, earning commission on rewards. Your stakers deposit BERA through smart contracts and receive liquid shares (stBERA) that automatically grow in value as rewards accumulate. +A staking pool lets you offer liquid staking to your community. Stakers deposit BERA and receive stBERA shares that grow as rewards compound. You earn commission on those rewards. -## What are staking pools? +## How a pool is put together -Staking Pools are validator-operated services that allow your community members to stake BERA through smart contracts, receiving liquid shares (stBERA) that represent their stake and automatically grow in value as rewards accumulate. Stakers can stake any amount without running their own validator. +`StakingPoolContractsFactory` deploys the contracts for one validator. Each pool includes: -As a validator, staking pools provide you with a way to build and monetize your own community of stakers, earning commission on rewards. Your stakers benefit from lower barriers to entry, automatic reward reinvestment, and flexible withdrawals. +- **StakingPool**: deposits, share accounting, and the stBERA token. Stakers call this contract. +- **SmartOperator**: validator operations and Proof of Liquidity. +- **StakingRewardsVault**: consensus-layer rewards, compounded back into the pool. -## Post-BGT Deprecation +Shared across pools: -The May 2026 Proof of Liquidity upgrade changes how staking pools earn and how stakers receive rewards. The contract surface and pool operations stay broadly the same. +- **WithdrawalVault**: withdrawal requests for every pool +- **AccountingOracle**: consensus-layer balances that feed `totalAssets` -- **Reward emissions are paid in \$WBERA.** Validator emissions accrue as \$WBERA on the `SmartOperator`. Operator monitoring views and the automatic flows that compound this WBERA into pool assets and into withdrawal coverage are documented in the [Operator Guide](/nodes/staking-pools/operators#automatic-wbera-flows). -- **Per-block emission is a flat fixed rate (no boost curve).** The pre-upgrade boost curve, which made BGT delegation a yield differentiator, is gone. Per-block emission no longer scales with delegation. Pools compete on **reward allocation strategy**, **attracted incentives**, and **commission rate** rather than boost. -- **BGT is deprecated.** We recommend unboosting and burning the BGT held by your `SmartOperator`. The BGT-era entry points stay callable but become inert once chargeable BGT is exhausted; see [Deprecated BGT entry points](/nodes/staking-pools/operators#deprecated-bgt-entry-points). -- **Withdrawals can be covered from operator-side WBERA.** The shared `WithdrawalVault` may pull from `availableWBERABalance()` on your `SmartOperator`, unwrap to native BERA, and apply that toward an outstanding request — fully, partially, or not at all when liquidity is insufficient. The standard consensus-layer withdrawal path remains for any uncovered remainder. +`StakingPool` inherits stBERA share mint, burn, and asset conversion. -For broader PoL changes, see [What's New](/general/proof-of-liquidity/changelog). +## What changed after BGT deprecation -## How it works +The May 2026 Proof of Liquidity upgrade changed how pools earn. The contract surface stays largely the same. -When you create a staking pool, the system deploys several interconnected contracts. Your pool includes a StakingPool contract that manages deposits and shares, a SmartOperator that handles validator operations and Proof of Liquidity integration, and a StakingRewardsVault that collects and reinvests rewards. Shared infrastructure includes a WithdrawalVault that processes withdrawal requests for all pools and an Accounting Oracle that provides consensus layer data updates. +- **Reward emissions are paid in $WBERA.** Validator emissions accrue as $WBERA on `SmartOperator`. See [Automatic WBERA flows](/nodes/staking-pools/operators#automatic-wbera-flows). +- **Per-block emission is a flat rate.** It no longer scales with BGT delegation. Pools compete on reward allocation, attracted incentives, and commission. +- **BGT is deprecated.** Unboost and burn BGT held on your `SmartOperator`. BGT-era entry points stay callable until chargeable BGT is gone. See [Deprecated BGT entry points](/nodes/staking-pools/operators#deprecated-bgt-entry-points). +- **Withdrawals can use operator WBERA.** `WithdrawalVault` may pull `availableWBERABalance()` from your `SmartOperator`, unwrap to BERA, and apply it in full, in part, or not at all. Uncovered remainder still exits through the consensus layer. -The system automates staking, reward distribution, and withdrawal management, requiring minimal manual intervention from you while providing your stakers with a seamless staking experience. +For the rest of the upgrade, see [What's New](/general/proof-of-liquidity/changelog). -### Contract architecture +## Who can do what -The staking pools system uses a factory pattern where the **StakingPoolContractsFactory** serves as the deployment mechanism, creating and managing the complete suite of contracts needed for each validator's staking pool. +`DEFAULT_ADMIN_ROLE` governs upgrades and emergency actions. `VALIDATOR_ADMIN_ROLE` is scoped to your pool. -The core functionality revolves around the **StakingPool** contract, which handles staker deposits, share management, and the fundamental operations of your staking pool. Stakers interact with this contract to stake their BERA tokens and receive stBERA shares in return. The StakingPool contract maintains the accounting for staker positions and manages the conversion between BERA and stBERA shares. +Other roles: -Validator operations are coordinated through the **SmartOperator** contract, which manages integration with Berachain's Proof of Liquidity system. This contract handles reward allocation, commission management, and validator-specific PoL operations. +- `REWARDS_ALLOCATION_MANAGER_ROLE`: reward allocation +- `COMMISSION_MANAGER_ROLE`: commission +- `PROTOCOL_FEE_MANAGER_ROLE`: protocol fee +- `INCENTIVE_COLLECTOR_MANAGER_ROLE`: incentive collector -The **StakingPool** contract inherits from the **stBERA** base contract, which provides the core token functionality for staked BERA shares, including share minting, burning, and conversion between assets and shares. +Contracts can pause. If deposits fall below the minimum effective balance, the pool can trigger a full exit. -### Security model +## What stakers see -The staking pools system implements a security model designed to protect staker funds while maintaining operational flexibility for validators and administrators. +Stakers deposit BERA and receive stBERA immediately. Rewards compound into share price. They can withdraw without a validator minimum. -Access control is managed through a role-based system that provides granular permissions for different types of operations. The `DEFAULT_ADMIN_ROLE` provides governance control over contract upgrades and emergency actions. Validators receive the `VALIDATOR_ADMIN_ROLE`, which grants them operational control over their specific staking pool while preventing interference with other validators' operations. +Withdrawal liquidity can come from: -Specialized roles handle specific aspects of the system. The `REWARDS_ALLOCATION_MANAGER_ROLE` manages reward allocation to specific applications, while the `COMMISSION_MANAGER_ROLE` handles validator commission management. The `PROTOCOL_FEE_MANAGER_ROLE` controls protocol fee settings, and the `INCENTIVE_COLLECTOR_MANAGER_ROLE` manages incentive collector operations. +- the consensus layer +- buffered funds on the pool before activation +- WBERA on your `SmartOperator`, via `WithdrawalVault` (full, partial, or none) -Emergency controls provide additional protection. Contracts can be paused in emergency situations. The system includes automatic full exit triggers that activate if the minimum balance threshold is breached, protecting stakers from potential losses. - -## Staker experience - -When stakers interact with your staking pool, they deposit BERA and immediately receive liquid stBERA shares. Rewards automatically compound as you earn rewards, increasing the value of shares over time without manual claiming or reinvestment. Stakers can withdraw at any time. **Withdrawal liquidity** can come from the **consensus layer**, from **buffered funds** on the pool before activation, and — after PoL Next on the staking-pools stack — from **WBERA held on your pool's `SmartOperator`**, which the shared **`WithdrawalVault`** may use to help satisfy requests (including **partial** coverage, with any remainder still exiting via the consensus layer). **Finalizing** a withdrawal request remains subject to the on-chain delay from the request block (commonly on the order of **three days** / **129,600** blocks at ~2s block time); see the [Operator Guide](/nodes/staking-pools/operators#withdrawal-system) for operator responsibilities and how coverage is sourced. Stakers can stake any amount without validator minimums, with full transparency through on-chain verification. +Finalizing a request waits until `requestBlock + 129,600` blocks (about three days at ~2s). See the [Operator guide](/nodes/staking-pools/operators#withdrawal-system). - **Staking pool shares (stBERA) are not LSTs.** They cannot be registered with - `IncentivesCollector` as an `LSTStakerVault` asset and cannot be deposited into the \$sWBERA - Staking Vault. Pool-level yield reaches stBERA holders through the pool's own `SmartOperator` and - `IncentiveCollector` — a separate path from the PoL Incentive Auction yield. + stBERA is not an LST. It cannot be registered with `IncentivesCollector` as an `LSTStakerVault` + asset, and it cannot be deposited into the $sWBERA Staking Vault. Pool yield reaches holders + through this pool's `SmartOperator` and `IncentiveCollector`, not through the PoL Incentive + Auction. -## Validator operations - -You deploy a staking pool through the factory contract, which creates all necessary contracts and registers your validator with the consensus layer. You configure commission rates (up to 20% of staker rewards) and can direct Proof of Liquidity incentives to specific applications. Commission is collected automatically on staker rewards, allowing you to focus on community building rather than manual reward management. - -## Integration with Proof of Liquidity - -Staking pools integrate with Berachain's Proof of Liquidity system. Pool reward flows route validator emissions to configured vault paths, and smart contracts claim and distribute PoL incentives. You can direct rewards to specific applications or ecosystem initiatives. - -## Provided tools - -Berachain provides tools to help you operate your staking pool. A React-based **example frontend template** provides a starting point for building your staking interface. The template demonstrates how stakers can connect wallets, deposit BERA, view positions, and request withdrawals. See the [Building your front-end](/nodes/staking-pools/operators#building-your-front-end) section in the operator guide for requirements and template usage. Bash scripts automate deployment and management operations, generating ready-to-review `cast` commands for safe execution. An interactive Python CLI tool is available for managing SmartOperator contracts. These tools are available in the [Berachain guides repository](https://github.com/berachain/guides/tree/main/apps/staking-pools), with detailed documentation in the [install-helpers README](https://github.com/berachain/guides/blob/main/apps/staking-pools/install-helpers/README.md). - -## Getting started +## What you operate -Validators can set up staking pools using the [Installation Guide](/nodes/staking-pools/installation) and manage operations with the [Operator Guide](/nodes/staking-pools/operators). +You deploy through the factory, which registers the validator. Commission is up to 20% of staker rewards and collects automatically. You can direct Proof of Liquidity incentives to specific applications. -## Smart contract reference +## Tools -For detailed information about the smart contracts and their functions, see the [Smart Contract Reference](/nodes/staking-pools/contracts). +Use [`install.sh`](https://github.com/berachain/guides/tree/main/apps/staking-pools/install-helpers/install.sh) in `install-helpers/` to install a pool. A React [example frontend](/nodes/staking-pools/operators#building-your-front-end) covers post-install staker operations. The Python SmartOperator Manager CLI manages operator contracts on the validator. -## Support and resources +Start with [Install a staking pool](/nodes/staking-pools/installation). Day-two work is in the [Operator guide](/nodes/staking-pools/operators). Addresses and ABIs are in [Look up staking pool contract addresses](/nodes/staking-pools/contracts). -If you don't have contact with Berachain Validator Relations, ask on our [Discord](https://discord.gg/berachain) **#node-support** channel. +If you don't have Validator Relations contact, ask in the [Discord](https://discord.gg/berachain) **#node-support** channel. diff --git a/scripts/contracts/generate-pages.mjs b/scripts/contracts/generate-pages.mjs index b2c3f7b..556c19c 100644 --- a/scripts/contracts/generate-pages.mjs +++ b/scripts/contracts/generate-pages.mjs @@ -394,37 +394,35 @@ The following is a list of contract addresses for interacting with Berachain BEX function renderStakingPoolsPage() { return `--- -title: "Staking Pool Contracts" -description: "Addresses and ABIs for StakingPoolContractsFactory, DelegationHandlerFactory, WithdrawalVault, and per-pool proxies (StakingPool, SmartOperator, etc.)." +title: "Look up staking pool contract addresses" +description: "Singleton addresses and ABIs, plus the per-pool proxies StakingPoolContractsFactory deploys." --- import StakingPoolSingletonsTable from "/snippets/contracts/generated/staking-pools-singletons-table.mdx"; -This reference provides contract addresses and links to detailed documentation for each contract in the staking pools system. For an overview of how the contracts work together, see the [Staking Pools Overview](/nodes/staking-pools/overview). +This page lists staking-pool contract addresses and ABI links. The [Staking pools overview](/nodes/staking-pools/overview) explains how the contracts fit together. -## Contract addresses +## Singleton contracts -### Singleton contracts - -Singleton contracts are deployed once and shared across all staking pools. The **StakingPoolContractsFactory** is the entry point for deploying a staking pool: you call it to create and register your pool's contracts. The **DelegationHandlerFactory** deploys per-validator delegation handler proxies when using foundation delegation. The other singletons below are shared infrastructure. +These contracts are deployed once and shared by every pool: -### Deployed contracts (per pool) +Call \`StakingPoolContractsFactory\` to create and register a pool. Call \`DelegationHandlerFactory\` to deploy a per-validator handler proxy for Foundation delegation. The other rows are shared infrastructure. -When you deploy a staking pool through the StakingPoolContractsFactory, the factory creates proxy contracts for your validator. These proxy contracts are what you and your stakers interact with directly. Each validator receives unique proxy addresses for these contracts when deploying their staking pool. +## Per-pool proxy contracts -The factory returns these proxy addresses when you call \`deployStakingPoolContracts\`. Store these addresses for your operations and provide the StakingPool address to your stakers for deposits. +\`deployStakingPoolContracts\` returns proxy addresses for your validator. You and your stakers call those proxies. Store the addresses. Give stakers the StakingPool address for deposits. -**Proxy contracts deployed with your pool:** +Proxy contracts for each pool: -- **StakingPool**: Main staking functionality and staker interactions. This is the contract address your stakers use to deposit BERA and receive stBERA shares. -- **SmartOperator**: Validator operations and Proof of Liquidity integration. -- **IncentiveCollector**: Incentive token collection and conversion. Handles the incentive auction mechanism where accumulated tokens can be claimed. -- **StakingRewardsVault**: Reward collection and automatic reinvestment. Automatically compounds rewards from the consensus layer. -- **DelegationHandler**: Delegation handling for capital providers. Only deployed if you're using delegated funds from the Berachain Foundation. +- **StakingPool**: deposits, shares, and staker interactions. Stakers deposit BERA here and receive stBERA. +- **SmartOperator**: validator operations and Proof of Liquidity integration. +- **IncentiveCollector**: incentive token collection, conversion, and the incentive auction. +- **StakingRewardsVault**: consensus-layer reward collection and compounding. +- **DelegationHandler**: Foundation-delegated capital. Deployed only on the delegated path. -For detailed technical documentation of each contract's functions and behavior, see the [Berachain guides repository](https://github.com/berachain/guides/tree/main/apps/staking-pools) and the [install-helpers README](https://github.com/berachain/guides/blob/main/apps/staking-pools/install-helpers/README.md). +ABI JSON for each singleton is in the table above. For install and operator flows, see [Install a staking pool](/nodes/staking-pools/installation) and the [Operator guide](/nodes/staking-pools/operators). `; }