| The WhitePaper Reading Club - DevConnect - Nov 16th 2025 | |
|---|---|
| Berachain: Prague3 HardFork | Rez (Berachain) |
Original Post: https://x.com/RezMah/article/1989172438031122499
Overview
$128M exploit came from a single bug: the EXACT_OUT swap path rounded the output amount down instead of up, making the pool think users were taking slightly less than they actually were. In normal LP pools this is tiny, but in composable pools (where the pool’s own LP token is tradable), attackers could force liquidity extremely low, amplifying the rounding error. This let them lower the invariant and profit from round-trip swaps. BEX on Berachain inherited this same bug, allowing the attacker to repeat the exploit and drain ~$12M from the ENA/HONEY pool. Berachain halted the chain and hard-forked to freeze stolen funds, fix the rounding logic, and resume the network safely.
The extractor says they will return the funds once the chain is live.
function _upscale(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) { // Upscale rounding wouldn't necessarily always go in the same direction: in a swap for example the balance of // token in should be rounded up, and that of token out rounded down. This is the only place where we round in // the same direction for all amounts, as the impact of this rounding is expected to be minimal (and there's no rounding error unless _scalingFactor() is overriden). return FixedPoint.mulDown(amount, scalingFactor);} |
|---|
Rejected Approaches
| Forced Token Recovery | (i) Hard-coded state transition to move ERC20s from exploiter wallets to a foundation wallet. (ii) High risk of mistakes during incident pressure. (iii) Requires full, accurate wallet list. (iv) Attackers could front-run before fork activation. |
|---|---|
| ERC20 Transfer Freeze | (i) Block ERC20 transfers to/from exploiter wallets using receipt-log detection. (ii) Allow only transfers to a governance rescue wallet. (iii) Works even if attacker uses approvals or alternate EOAs. (iv) Most minimal and safe hard fork logic. |
| BEX Freeze Layer | (i) Block all ERC20 transfers involving the BEX vault. (ii) Block InternalBalanceChanged events to prevent internal vault movements. (iii) Avoid deeper Revm-level changes unsuitable for emergency response. |
| Chain Halt + Fork Execution | (i) Halt chain to freeze world state and prevent fund movement. (ii) Activate fork at timestamp immediately after last valid block. (iii) Validators restart with updated genesis + fork config. |

Final Solution
Prague3 Hard Fork: (i) Chain halt → deterministic fork rollout. (ii) ERC20 transfer blocking for all exploiter wallets except transfers to the rescue wallet. (iii) Blocking of BEX vault ERC20 transfers and key internal balance-change events. (iv) Matching validation + block-builder commit-condition rules to reject violating blocks. (v) Exfiltration is impossible; whitehat can only return funds. (vi) Validators upgraded to new binaries and chain resumed safely; funds recovered.
Future Improvements
-
Emergency Freeze Fork Template: (i) Maintain pre-tested binaries enabling full freeze of BERA, ERC20, and ERC721 from specified addresses. (ii) Reduces response time and incident-era risk. (iii) Still requires short-term chain halt.
-
Oracle-Injected Blocklist (Optional, No Halt Needed): (i) Consensus or execution clients read blocklist updates from an authorized oracle. (ii) Allows near-instant freezing mid-attack. (iii) Potential race conditions before oracle update. (iv) Introduces decentralization and trust tradeoffs.