Value is unsafely downcasted and truncated from uint256 to uint96 .
function claimDittoMatchedReward(uint256 vault) external nonReentrant {
STypes.Vault storage Vault = s.vault[vault];
STypes.VaultUser storage VaultUser = s.vaultUser[vault][msg.sender];
uint88 shares = VaultUser.dittoMatchedShares;
if (shares <= 1) revert Errors.NoShares();
shares -= 1;
uint256 protocolTime = LibOrders.getOffsetTime() / 1 days;
uint256 elapsedTime = protocolTime - Vault.dittoMatchedTime;
uint256 totalReward =
Vault.dittoMatchedReward + elapsedTime * 1 days * Vault.dittoMatchedRate;
uint256 sharesTotal = Vault.dittoMatchedShares;
uint256 userReward = shares.mul(totalReward).div(sharesTotal);
if (elapsedTime > 0) {
Vault.dittoMatchedTime = uint16(protocolTime);
}
Vault.dittoMatchedShares -= shares;
if ((totalReward - userReward) > type(uint96).max) revert Errors.InvalidAmount();
175: Vault.dittoMatchedReward = uint96(totalReward - userReward);
VaultUser.dittoMatchedShares = 1;
if (userReward > type(uint80).max) revert Errors.InvalidAmount();
VaultUser.dittoReward += uint80(userReward);
emit Events.ClaimDittoMatchedReward(vault, msg.sender);
}
The loss is due to broken accounting if the value exceed uint96 , resulting in overflow and impacting rewards.
Manual code review.
The recommendation is made for using uint256 or apply Openzepplin’s SafeCast library.