sherlock-audit / 2023-04-footium-judging

13 stars 7 forks source link

0xPkhatri - User not able to claim Prizes in the FootiumPrizeDistributor#claimERC20Prize Function #362

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

0xPkhatri

medium

User not able to claim Prizes in the FootiumPrizeDistributor#claimERC20Prize Function

Summary

In the FootiumPrizeDistributor#claimERC20Prize function, which prevents users from claiming prizes if user eligible for second time or eligible for multiple prize for the same token. The issue arises due to the implementation of the totalERC20Claimed mapping that does not consider updated prize amounts for the same user.

Vulnerability Detail

The claimERC20Prize function calculates the value to be claimed by the user using the following line:

uint256 value = _amount - totalERC20Claimed[_token][_to];

If a user has already claimed a prize for a specific token and wins another prize, the value will be less than or equal to zero due to the totalERC20Claimed[_token][_to] being equal to or greater than the _amount. Consequently, the user will not be able to claim their new prize using the same _amount value.

Impact

This vulnerability affects users who have won multiple prizes for the same token or eligible for prize another time. They will not be able to claim their new prizes, resulting in a loss of rewards for users.

Code Snippet

https://github.com/sherlock-audit/2023-04-footium/blob/main/footium-eth-shareable/contracts/FootiumPrizeDistributor.sol#L106-L134

Tool used

Manual Review

Recommendation

update mapping for each Round of prize distribution

+    uint256 public roundNumber;
-    mapping(IERC20Upgradeable => mapping(address => uint256))
-        private totalERC20Claimed;
-    mapping(address => uint256) private totalETHClaimed;
+    mapping(roundNumber => mapping(IERC20Upgradeable => mapping(address => uint256)))
+        private totalERC20Claimed;
+    mapping(roundNumber => mapping(address => uint256)) private totalETHClaimed;
function claimERC20Prize(
    address _to,
    IERC20Upgradeable _token,
    uint256 _amount,
    bytes32[] calldata _proof
) external whenNotPaused nonReentrant {
    if (_to != msg.sender) {
        revert InvalidAccount();
    }

    if (
        !MerkleProofUpgradeable.verify(
            _proof,
            erc20MerkleRoot,
            keccak256(abi.encodePacked(_token, _to, _amount))
        )
    ) {
        revert InvalidERC20MerkleProof();
    }

-    uint256 value = _amount - totalERC20Claimed[_token][_to];
+    uint256 value = _amount - totalERC20Claimed[roundNumber][_token][_to];

    if (value > 0) {
-        totalERC20Claimed[_token][_to] += value;
+        totalERC20Claimed[roundNumber][_token][_to] += value;
        _token.transfer(_to, value);
    }

    emit ClaimERC20(_token, _to, value);
}

Duplicate of #18