The function WinnablesPrizeManager::claimPrize() is provided to claim the raffle prize for the winner. In its implementation, The winner can claim the prize of a raffle by providing the raffleId and The asset associated with this raffleId is transferred to the msg.sender address.
However, the checks for the claimed status of the raffle and whether the msg.sender is the winner of the raffle are implemented after the prize has been transferred and the status of the raffle is changed to CLAIMED only after the transfer has taken place.
If in an instance, msg.sender is a contract and not an EOA, the malicious actor could trigger reentrancy by repetitively calling the claimPrize() within a receive function and thus draining all the funds since there are no checks for the same before another interaction.
In Reentrancy, the state is updated after the external call and therefore, when reentered, the state is the same as the first call. The caller is a contract with a malicious receive function which calls the vulnerable claimPrize() function and because the checks and the state updation are implemented after the external calls, the funds get transferred again. This again receive for the caller which calls the claimPrize() function with the same state and the funds are drained completely.
Mitigation:
This vulnerability can be easily mitigated by using the checks-effects-interactions practice that helps to prevent reentrancy attacks. The code after this practice has been adhered to is as follows:
BlocSoc_Audits
High
[H-2] Possible Reentrancy in WinnablesPrizeManager::claimPrize()
File: WinnablesPrizeManager
Description:
The function WinnablesPrizeManager::claimPrize() is provided to claim the raffle prize for the winner. In its implementation, The winner can claim the prize of a raffle by providing the raffleId and The asset associated with this raffleId is transferred to the msg.sender address.
However, the checks for the claimed status of the raffle and whether the msg.sender is the winner of the raffle are implemented after the prize has been transferred and the status of the raffle is changed to CLAIMED only after the transfer has taken place. If in an instance, msg.sender is a contract and not an EOA, the malicious actor could trigger reentrancy by repetitively calling the claimPrize() within a receive function and thus draining all the funds since there are no checks for the same before another interaction.
In Reentrancy, the state is updated after the external call and therefore, when reentered, the state is the same as the first call. The caller is a contract with a malicious receive function which calls the vulnerable claimPrize() function and because the checks and the state updation are implemented after the external calls, the funds get transferred again. This again receive for the caller which calls the claimPrize() function with the same state and the funds are drained completely.
Mitigation:
This vulnerability can be easily mitigated by using the checks-effects-interactions practice that helps to prevent reentrancy attacks. The code after this practice has been adhered to is as follows:
Liklihood: High
Impact: HIgh
Tool used
Manual Review