A critical vulnerability exists in the VaultRouterBranch.stake()
function where users silently lose their unclaimed WETH rewards when staking additional shares. The vulnerability stems from the reward distribution mechanism's improper handling of lastValuePerShare
updates during staking operations. While the unstake()
function properly protects users by reverting if unclaimed rewards exist, stake()
lacks this protection, leading to permanent loss of rewards.
The Zaros protocol implements a sophisticated reward distribution system where WETH rewards are allocated to vault stakers proportionally to their share holdings. The system uses a cumulative reward tracking mechanism with three key components:
Global Reward Tracking:
valuePerShare
: A cumulative measure of rewards per share (in WETH)
Increases each time new rewards are distributed to the vault
Represents total historical rewards per share
User-Specific Tracking:
lastValuePerShare
: User's checkpoint for reward calculations
Updated when user claims rewards or modifies their stake
Used as the baseline for calculating unclaimed rewards
Reward Calculation:
The vulnerability manifests in the reward accumulation logic, specifically in how Distribution.accumulateActor()
is called during staking operations:
The core issue lies in how _updateLastValuePerShare()
modifies the user's reward checkpoint without ensuring rewards are claimed:
means if the user stake additional shares, the unclaimed rewards will be lost
To illustrate the vulnerability, consider this scenario:
Initial State (t0):
User Stakes More (t1):
Note that The unstake()
function correctly implements safety checks:
The vulnerability results in direct and permanent economic loss for stakers through:
Manual review
Add Protective Revert (like unstake):
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.