Lesson 7 — Reading bera-reth — Proof-of-Liquidity as consensus customization
Question
Berachain runs Proof-of-Liquidity — a consensus customisation where validator selection is based on staked liquidity (not just BGT tokens). Reading bera-reth shows how a real production chain customises consensus via Reth SDK.
Principle (minimum model)
- Proof-of-Liquidity (PoL). Validators are chosen by their liquidity provision (LP positions on the BGT pool) rather than just token stake. Aligns incentives between validators and liquidity providers.
- bera-reth implementation. Forks Reth SDK; overrides the
Consensustrait to use PoL's validator-selection logic. Uses Reth's execution engine unchanged. - Validator selection.
select_validators(epoch) -> Vec<Address>— queries the on-chain LP pool, ranks by liquidity, returns the top N. Called once per epoch. - Slashing customisation. PoL slashing burns LP positions instead of staked tokens. Custom slashing logic in the
validate_statehook. - Why this matters. Demonstrates how Reth SDK lets a chain customise consensus without forking the entire codebase. Bera-reth ships its custom
Consensusimpl + uses upstream Reth for everything else. - Trade-offs. PoL incentivises real liquidity but introduces validator-LP centralisation risk (big LPs dominate). Berachain mitigates via cap on LP-weight.
- Pattern for custom L1s. This is the template: fork Reth SDK lightly + override consensus + ship.
Worked example + steps
Reading bera-reth — Proof-of-Liquidity as consensus customization
Most "we have a different consensus" pitches turn out to be PoS with a renamed token. Berachain's Proof-of-Liquidity (PoL) is the rare exception: it actually changes who's allowed to validate and where the rewards go. And the implementation — berachain/bera-reth — is in production, on Reth, with the diff small enough to read in an afternoon.
This is the practical surface of "swap the consensus." If you want to know what a real custom L1 looks like on Reth, this is the one to study.
1. What Proof-of-Liquidity changes
The Berachain pitch:
- In PoS: validators stake a native token. The token's only utility is staking.
- In PoL: validators stake BGT (Bera Governance Token — Berachain's non-transferable governance asset), but BGT is earned by providing liquidity to BEX (BeraSwap, Berachain's native AMM/DEX).
The cascade:
- Users provide liquidity to BEX → earn BGT
- BGT can be staked → earn validator privileges
- Validators earn fees → flow back to LPs as rewards
This makes validator economics aligned with DEX liquidity. The chain's most active users (LPs) are also the most reward-aligned validators.
2. What stays the same as Ethereum PoS
A lot. PoL is PoS with a twist, not a new family:
| Feature | PoS | PoL | Same? |
|---|---|---|---|
| Validator set bounded | Yes (~1M) | Yes (smaller, e.g., ~100) | Same structure |
| Slashing for double-signing | Yes | Yes | Same |
| Finality gadget | Casper FFG | CometBFT-style | Different engine |
| Block time | 12s | ~2s | Different |
| Token model | Single (ETH) | Dual (BGT + Bera) | Different |
The fundamental consensus model (BFT-style finality, slashing) is the same. What changes is:
- Who can be a validator (LP-based gating)
- How rewards flow (back to LPs, not just stakers)
- Block time (faster, ~2s)
3. The Reth-side changes
Reading bera-reth's architecture:
bera-reth/
├── consensus/ ← Custom consensus impl
├── chainspec/ ← Berachain mainnet/testnet specs
├── evm/ ← Custom EVM config + precompiles
├── node/ ← NodeBuilder wiring
└── rpc/ ← bera_* RPC namespace
The customization points (same pattern as Tempo or any Reth-based L1):
3.1 consensus/
The Consensus trait impl validates Berachain-specific block properties:
- Proposer is in active validator set (LP-gated)
- Block timestamp within delta (fast 2s blocks have tighter timestamp bounds)
- Validator signature scheme: BLS aggregated signatures, not ECDSA
3.2 evm/
Custom precompiles for PoL economics:
- Reward distribution precompile: when a block commits, native rewards flow to LPs proportionally
- Validator registry precompile: track active validator set on-chain
Both of these are pre-execution hooks in the executor — they run before transactions, updating chain state automatically.
🔍 Find in repo. Open bera-reth's
evm/crate and find the executor impl. What hooks does it run before the first transaction in each block? This is the PoL reward flow.
4. The chain spec — what makes a chain "different"
bera-reth's chainspec shows what changes at the spec level:
- Custom fork heights: their own activation table for upgrades
- Custom genesis: BGT pre-mint, validator initial allocations
- Custom precompile addresses: PoL hooks at reserved addresses
- Custom base fee params: tuned for 2s blocks
This is structurally identical to Ethereum's chainspec but semantically different. Your custom L1 will have its own version.
5. Reading the consensus integration
Read in this order:
bera-reth/consensus/src/lib.rs— theConsensusimplbera-reth/node/src/lib.rs— where it's wired into NodeBuilderbera-reth/chainspec/src/lib.rs— what protocol parameters it depends onbera-reth/evm/src/lib.rs— what executor hooks run with this consensus
Each file is small (<500 lines). The whole bera-reth-as-consensus-customization is ~2000 lines on top of standard Reth.
That's the headline: a full custom L1 is 2000 lines of Reth customization if you have a Tendermint-style consensus engine ready. Most of the work is integration, not protocol re-implementation.
6. The lesson for your L1
Studying bera-reth as a reference:
- Your custom chain crate ~= bera-reth's crate structure
- Your
Consensusimpl ~= bera-reth's, with your validator set rules - Your executor hooks ~= bera-reth's PoL hooks, with your business logic
- Your NodeBuilder wiring ~= bera-reth's, calling your components
bera-reth is the template. Tempo's node crate (tempoxyz/tempo) is now public and you can verify the same shape directly — different business logic (payments-priority instead of PoL), same skeleton. Same compose-don't-fork pattern: their tempoxyz/reth is 0 commits ahead of upstream.
7. Practice
- Clone bera-reth (or browse on GitHub)
- Compare to the directory structure of reth's own
crates/optimism/from Expert Module 3 - Identify the 3 files most specific to PoL (the parts you'd most need to customize for a different L1)
- Estimate: if you forked bera-reth to make a Tempo-style L1, how much would you change vs keep?
Final check: in one sentence, what's the structural answer to "how do I ship a custom L1 on Reth?" If your answer is more than "implement the Consensus trait + custom executor hooks + NodeBuilder wiring," you're overcomplicating.
Summary (3 lines)
- bera-reth = Reth SDK fork with PoL (Proof-of-Liquidity) consensus. Validators picked by LP positions, not just stake.
- Custom Consensus trait + custom validator selection + custom slashing (burns LP positions). Execution engine unchanged.
- Template for custom L1s: fork Reth SDK lightly + override consensus + ship. Next: quiz on reading consensus internals.