DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Invalid

Off-by-one error in the `withdrawDittoReward` and `claimDittoMatchedReward` functions results in users receiving less Ditto token rewards on the initial call

Summary

Due to employing gas-saving techniques, users claiming and withdrawing their eligible Ditto rewards receive ~1 wei less Ditto rewards on the initial call.

Vulnerability Details

The withdrawDittoReward function, as well as the claimDittoMatchedReward function in the YieldFacet contract, decrement the amt and shares variables, respectively, by 1 wei before accounting it to the user. This is to save gas costs as it is more gas efficient for consecutive calls if the storage value is not reset to 0, but instead to a non-zero value of 1 wei.

However, this results in the user receiving fewer Ditto token rewards the first time the above-mentioned functions are called due to subtracting 1 wei from the user's amt and shares balances. On consecutive calls, though, the user receives the correct amount of Ditto token rewards as the amt and shares balances are always reset to 1 wei, and this 1 wei has to be subtracted again.

As this results in every user receiving fewer Ditto token rewards on the initial call, the likelihood is high, but due to only causing an almost[^1] negligible loss of around 1 wei per user, the impact is low. Resulting in a medium severity rating.

[^1]: The loss is not exactly 1 wei as the decremented shares variable is used to calculate the userReward value., which is then used as the amt value in the withdrawDittoReward function. This slightly amplifies the loss.

contracts/facets/YieldFacet.sol#L195

189: function withdrawDittoReward(uint256 vault) external nonReentrant {
190: STypes.VaultUser storage VaultUser = s.vaultUser[vault][msg.sender];
191: uint256 amt = VaultUser.dittoReward;
192: // Implicitly checks for a valid vault
193: if (amt <= 1) revert Errors.NoDittoReward();
194: // Decrease by 1 wei to account for 1 wei gas saving technique
195: ❌ amt -= 1;
196: VaultUser.dittoReward = 1; // keep as non-zero to save gas
197: DITTO.mint(msg.sender, amt);
198: }

Same with the shares variable in the claimDittoMatchedReward function in line 159.

Impact

Users claiming and withdrawing their eligible Ditto rewards receive ~1 wei less Ditto rewards on the initial call.

Tools Used

Manual Review

Recommendations

Consider adding 1 wei to the amt and shares variables on the initial call to the withdrawDittoReward and claimDittoMatchedReward functions.

Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-556

T1MOH Auditor
almost 2 years ago
0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.