This segment is prone to an integer overflow. The multiplication totalRewards[poolID] * increaseShareAmount can produce a result larger than what uint128 can hold (maximum value of (2^{128} - 1)), especially when increaseShareAmount is significantly larger than existingTotalShares. Upon overflow, virtualRewardsToAdd gets wrongly truncated to a uint128, leading to an incorrect, potentially much smaller value being added to user.virtualRewards and totalRewards[poolID].
The overflow can result in an erroneous computation of virtual rewards, thereby allowing users like Bob in the provided Proof of Concept (POC) to unjustly claim a disproportionate share of the rewards. This not only leads to an unfair distribution of rewards but also poses a risk of depleting the reward pool, causing financial discrepancies and potentially undermining the integrity of the smart contract system.
Initial Reward Allocation: 100 * 10^18 SALT is allocated to an initially empty pool.
Alice's Action: Alice deposits 101 wei of a token, setting totalShares to 202.
Alice's Reward Claim: As the sole participant, Alice is entitled to the entire reward pool of 100 * 10^18 SALT by using claimAllRewards().
Bob's Deposit: Bob deposits 350 ether (350 * 10^18 wei), causing an overflow in the virtualRewardsToAdd calculation.
Result of Overflow: The calculation of virtualRewardsToAdd overflows and gets truncated, leading to an incorrect update of user.virtualRewards and totalRewards[poolID].
Unjust Reward Claim: Bob is now able to claim an undeserved amount of approximately 99 SALT, either causing a revert due to insufficient rewards or leading to an accounting error.
Tools Used
foundry
Recommended Mitigation Steps
Since the overflow issue stems from typecasting a large uint256 value to uint128, a reevaluation of the data types used is necessary. The virtualRewardsToAdd should remain as a uint256 to accommodate the potential large values resulting from the multiplication. Furthermore, revisiting the reward calculation algorithm to introduce checks or limits that prevent such disproportionate increases in virtualRewardsToAdd would be prudent.
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/main/src/staking/StakingRewards.sol#L83
Vulnerability details
Impact
The vulnerability exists in the following code segment within the
_increaseUserShare
function:This segment is prone to an integer overflow. The multiplication
totalRewards[poolID] * increaseShareAmount
can produce a result larger than whatuint128
can hold (maximum value of (2^{128} - 1)), especially whenincreaseShareAmount
is significantly larger thanexistingTotalShares
. Upon overflow,virtualRewardsToAdd
gets wrongly truncated to auint128
, leading to an incorrect, potentially much smaller value being added touser.virtualRewards
andtotalRewards[poolID]
.The overflow can result in an erroneous computation of virtual rewards, thereby allowing users like Bob in the provided Proof of Concept (POC) to unjustly claim a disproportionate share of the rewards. This not only leads to an unfair distribution of rewards but also poses a risk of depleting the reward pool, causing financial discrepancies and potentially undermining the integrity of the smart contract system.
Proof of Concept
totalShares
to 202.claimAllRewards()
.virtualRewardsToAdd
calculation.virtualRewardsToAdd
overflows and gets truncated, leading to an incorrect update ofuser.virtualRewards
andtotalRewards[poolID]
.Tools Used
foundry
Recommended Mitigation Steps
Since the overflow issue stems from typecasting a large
uint256
value touint128
, a reevaluation of the data types used is necessary. ThevirtualRewardsToAdd
should remain as auint256
to accommodate the potential large values resulting from the multiplication. Furthermore, revisiting the reward calculation algorithm to introduce checks or limits that prevent such disproportionate increases invirtualRewardsToAdd
would be prudent.Assessed type
Math