| brip | 6 |
|---|---|
| title | Baseline Cutting Board Automation |
| author | astro-bera, bar-bera, GrizzlyBera |
| status | Draft |
| created | 2025-10-17 |
| type | PoL |
| requires | BRIP-0004 |
This BRIP proposes a default ‘baseline’ validator reward allocation strategy - aka ‘cutting board’. This default cutting board will be automatically maintained by the Berachain Foundation using a simple, clearly specified protocol. The cutting board will act as a ‘fallback’ strategy for validators that choose not to proactively manage their reward allocation themselves. The mechanism that triggers the ‘fallback’ will be defined and managed by the Proof of Liquidity protocol.
This BRIP is meant to be complementary to BRIP-0005 and does not override the ability for validators to proactively manage their cutting board.
Despite continuing improvements to the efficiency and usability of the Proof of Liquidity protocol, it remains a challenge for validators to manage their cutting boards in an efficient and timely manner. This results in diminished economic efficiency of the overall system as validator BGT emissions are often allocated to vaults with little or no active incentives.
While BRIP-0005 proposes a more flexible mechanism for validators to delegate their cutting board management to an external ‘sidecar’, the design and implementation of this sidecar remains undefined and would entail significant effort and require substantial expertise.
This BRIP proposes a middle ground solution where an external service manages the complexity of monitoring and administering a simple, baseline cutting board. Validators are still free to manage their cutting board but can trivially fall back to this default strategy without any protocol interaction or additional infrastructure requirements.
This BRIP proposes changes to the Proof of Liquidity protocol. Specifically, it introduces the concept of an ‘baseline’ cutting board which can be managed by an external account that is granted a new role, the ‘ALLOCATION_SETTER’ role.
It also defines a simple mechanism that determines when validators automatically ‘revert’ to using this baseline strategy. In this initial proposal, the mechanism is defined through inactivity; specifically if a validator chooses to not update their cutting board within a defined period the protocol switches the validator to the baseline strategy. This inactivity period is specified in terms of block count and is governed by a protocol-defined parameter which is managed by Berachain governance.
Automatic update of the baseline cutting board will be handled by an off-chain foundation-controlled bot. This bot will monitor the state of incentives in all active vaults and periodically update the baseline strategy in accordance with a simple function. While the details of the implementation of the bot are beyond the scope of this BRIP, the baseline strategy will be specified below.
In green are new components; in yellow are existing modified components.
- RewardAllocatorFactory - new contract
- Baseline allocation definition holder.
- Uses standard OpenZeppelin
AccessControlUpgradeableto define and manageALLOCATION_SETTERrole. - Defines and implements
setOptimalAllocationmethod to allow baseline reward allocation to be modified. Permission to execute method is assigned toALLOCATION_SETTERrole.
- Berachef - modifications
- Modify behavior of
getActiveRewardAllocation: implementation of the fallback mechanism; add call to_checkInactivity. _checkInactivitychecks requested validator's current reward allocation for activity marker (block number). If reward allocation activity marker is not withinraInactivityBlockSpanblocks, baseline allocation is used.raInactivityBlockSpansystem parameter is added.- Setter and getters added for
raInactivityBlockSpanadded. Permission to modify granted to existingOwnerrole - currently Berachain governance. rewardAllocatorFactoryattribute is added and initialized to refer to defaultRewardAllocatorFactoryinstance.
- Modify behavior of
PRICE_TTL - The maximum time-to-live of an incentive token price update before it is considered "stale".
Currently, the strategy will rely on Pyth as the authoritative source of pricing incentive tokens in USD.
The system will estimate maxBgtPerProposal.
Detailed explanation for interested parties
When vaults are close to running out of an incentive token, higher BGT emitters will consume all remaining incentives and miss out on potential earnings had they chosen a different vault, while lower BGT emitters can capitalize on remaining incentives. For this reason, calculating the perfectly optimal allocation strategy requires knowledge of how much BGT a validator is expected to emit in a future block.
Determining the expected amount of BGT emission is outside the scope of this specification. Implementors are encouraged to optimize for a single validator, allowing this value to be derived by getting the validator's current boostPower := BGT.boostees[valPubkey] / BGT.totalBoosts, then calling BlockRewardController.computeReward(boostPower, self.rewardRate, self.boostMultiplier, self.rewardConvexity) * 1e-18 * (BeraChef.maxWeightPerVault / 1e4), for which the respective units are:
In the case of Berachain maintaining a baseline allocation for all validators, we will instead approximate the next expected BGT emission amount. We do so by taking the maximum value extracted from RewardVault#BGTBoosterIncentivesProcessed events over the last
Let maxBgtPerProposal be the maximum expected amount of BGT that can be emitted to a single vault in the next block (see Expected BGT Emission).
Let yields := Array<{Vault, Yield}>().
For each whitelisted reward vault:
- Let
yieldUsdPerBgt := 0, which will accumulate value in the subsequent for-loop. - For each whitelisted incentive token returned by
RewardVault#getWhitelistedTokens():- Get token price from Pyth. If missing price data, or last updated timestamp is older than
PRICE_TTL, then → skip this token. - Let
incentive := RewardVault#incentives(tokenAddr) - If the amount of token remaining is zero, given by
incentive.amountRemaining, then → skip this token. - Let
emissionUsdPerBgt := tokenPriceUsd * incentive.incentiveRate * pow(10, -token.decimals), for which the respective units are:$\frac{USD}{BGT} = \frac{USD}{TKN} \times \frac{TKN \times 10^{N}}{BGT} \times 10^{-N}$ , where$N$ is the number of decimals of the incentive token. - Let
amountRemainingUsd := incentive.amountRemaining * pow(10, -token.decimals) * tokenPriceUsd, for which the respective units are:$USD = (TKN \times 10^{N}) \times 10^{-N} \times \frac{USD}{TKN}$ , where$N$ is the number of decimals of the incentive token. - Let
maxUsdPerProposal := maxBgtPerProposal * emissionUsdPerBgt, for which the respective units are:$USD = BGT \times \frac{USD}{BGT}$ - If
maxUsdPerProposalis greater thanamountRemainingUsd, then → setemissionUsdPerBgt = amountRemainingUsd / maxBgtPerProposal, for which the respective units are:$\frac{USD}{BGT} = USD \div BGT$ - At this point,
emissionUsdPerBgtscores the potential profitability of this incentive. The unit is in expected USD per BGT, as a rate of return. Since each vault may have multiple incentives, accumulate this score toyieldUsdPerBgt += emissionUsdPerBgt - end of incentives for-loop
- Get token price from Pyth. If missing price data, or last updated timestamp is older than
- If
yieldUsdPerBgtis zero, then → skip this vault. - Update the array:
append(yields, {vault, yieldUsdPerBgt}). - end of vaults for-loop
If len(yields) is zero, return NO_STRATEGY.
Let rankings := sort(yields by (a, b) => a.Yield > b.Yield).
Let allocations := Array<{Vault, Weight}>().
Let i := 0, and weightRemaining := 100_00 bps (100% in bips). While i < min(len(rankings), BeraChef.maxNumWeightsPerRewardAllocation) and weightRemaining > 0:
- Let
maxBps := min(weightRemaining, BeraChef.maxWeightPerVault); allocating as much BGT to this vault as possible. - Update
weightRemaining -= maxBps; accounting for remaining weight available to allocate. - Let
ranking := rankings[i] - Update
append(allocations, {ranking.vault, maxBps}); saving the allocation for this vault.
Return allocations.
end of algoritm
While not a direct alternative, this BRIP can be thought of as accomplishing similar goals to BRIP-0005. While BRIP-0005 allows for maximum flexibility and customization by validators, it also entails significant complexity and increases the operational cost and requirements for a validator.
This BRIP also addresses an additional issue, which could be characterized as the ‘passive validator’ issue. In the current implementation of Proof of Liquidity, validators that choose to not manage their cutting boards contribute to an overall degradation of the economic efficiency of the protocol. Specifically, BGT is allocated without any incentives accrued to stakeholders. This BRIP addresses this issue while BRIP-0005 does not.
- No breaking protocol changes or incompatibilities
- Change in ‘default’ behavior: there is already a ‘default’ cutting board. Previously if a validator never changed their cutting board or - somehow - ended up with an invalid cutting board, this default would be returned.
- Unit tests defined as part of smart contract implementation
- Smart contract changes to be open-sourced in a timely manner
- Implementation of bot to be open-sourced in a timely manner
- Smart contract changes to be audited as per normal procedure. Results of audits will be made public in a timely manner.
- The offchain bot will be managed by the Berachain Foundation with standard security best practices. The ‘hot key’ (EOA) required for this bot will have only the minimum capabilities necessary for its function.
All copyrights and related rights in this work are waived under CCO 1.0 Universal.
