Open c4-bot-4 opened 9 months ago
othernet-global (sponsor) confirmed
virtualRewards and userShare are now uint256 rather than uint128.
Fixed in: https://github.com/othernet-global/salty-io/commit/5f79dc4f0db978202ab7da464b09bf08374ec618
Considering that you could time this to break in the future and that it seems easily doable by an attacker on a new pool, High severity seems justified under "Loss of matured yield".
Picodes marked the issue as satisfactory
Picodes marked the issue as selected for report
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/StakingRewards.sol#L81
Vulnerability details
Impact
Staking in SALTY pools happens automatically when adding liquidity. In order to track the accrued rewards, the code "simulates" the amount of virtual rewards that need to be added given the increase of shares and lend this amount to the user. So, when computing the real rewards for a given user, the code will compute its rewards based on the
totalRewards
of the given pool minus the virtual rewards. The following code computes the virtual rewards for a user:https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/StakingRewards.sol#L81
Basically, it aims to maintain the current ratio of
totalRewards
andexistingTotalShares
. The issue with this is that allows the first depositor to set the ratio too high by donating some SALT tokens to the contract. For example, consider the following values:The returned value is in order of 39-40 digits. Which is beyond what 128 bits can represent:
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/StakingRewards.sol#L83-L84
This will broke the reward computations. For a more concrete example look the PoC.
Proof of Concept
The following coded PoC showcase an scenario where the first depositor set the
rewards / shares
ratio too high, causing the rewards system to get broken. Specifically, it shows how the sum of the claimable rewards for each user is greater than the SALT balance of the contract.It should be pasted under
Staking/tests/StakingRewards.t.sol
.Tools Used
Manual Review
Recommended Mitigation Steps
Some options:
Make the function
addRewards
in theStakingRewards
contract permissioned. In this way, all rewards will need to go through the emitter first.Do not let the first depositor to manipulate the initial ratio of rewards / share. It is possible for every pool to burn the initial 10000 shares and starts with an initial small amount of rewards, kind of simulating being the first depositor.
Assessed type
Other