A malicious player could call MergingPool.claimRewards() using a contract. This function mints multiple fighter using FighterFarm.mintFromMergingPool(). A malicious user can build an attacker contract that implements Openzeppelin.IERC721Receiver overriding the onERC721Received() which is triggered by _mint() action. This malicious method could reenter calling MergingPool.claimRewards() again, before the first call is finished, obtaining more fighters than he should have.
Recommended Mitigation proposed by wardens
The mitigation proposal is to use the nonReentrant modifier on MergingPool.claimRewards():
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
They are both protected against reentrancy: FighterFarm.claimFighters() thanks to [L230-L231] which changes at every call and avoids using the same signature twice, FighterFarm.redeemMintPass() thanks to the fact that the used mintPass is burned. However, we suggest protecting both using OpenZeppelin ReentrancyGuard, because they mint a new ERC721 token and so they both could trigger the onERC721Received method of a malicious contract. In future development, without this protection, some vulnerabilities could be introduced.
Lines of code
Vulnerability details
Lines of code
Old lines of code
https://github.com/code-423n4/2024-02-ai-arena/blob/f2952187a8afc44ee6adc28769657717b498b7d4/src/MergingPool.sol#L9
https://github.com/code-423n4/2024-02-ai-arena/blob/f2952187a8afc44ee6adc28769657717b498b7d4/src/MergingPool.sol#L139-L145
Mitigated lines of code
https://github.com/ArenaX-Labs/2024-02-ai-arena-mitigation/blob/fix-47/src/MergingPool.sol#L5 https://github.com/ArenaX-Labs/2024-02-ai-arena-mitigation/blob/fix-47/src/MergingPool.sol#L11 https://github.com/ArenaX-Labs/2024-02-ai-arena-mitigation/blob/fix-47/src/MergingPool.sol#L142-L149
Vulnerability details
The issue was reported in #37.
The issue is because MergingPool.claimRewards() is vulnerable to reentrancy.
A malicious player could call
MergingPool.claimRewards()
using a contract. This function mints multiplefighter
usingFighterFarm.mintFromMergingPool()
. A malicious user can build an attacker contract that implements Openzeppelin.IERC721Receiver overriding the onERC721Received() which is triggered by_mint()
action. This malicious method could reenter callingMergingPool.claimRewards()
again, before the first call is finished, obtaining morefighters
than he should have.Recommended Mitigation proposed by wardens
The mitigation proposal is to use the
nonReentrant
modifier onMergingPool.claimRewards()
:This solution was implemented by the Ai Arena team.
Comment about the Mitigation Proposal
This mitigation is commonly used to avoid
Reentrancy
attacks. According to OpenZeppelin Documentation:So, it will not be possible to call
We consider this issue mitigated. We want to add the we found another core functions that should be protected against reentrancy: FighterFarm.claimFighters() and FighterFarm.redeemMintPass()
They are both protected against reentrancy:
FighterFarm.claimFighters()
thanks to [L230-L231] which changes at every call and avoids using the same signature twice,FighterFarm.redeemMintPass()
thanks to the fact that the usedmintPass
is burned. However, we suggest protecting both usingOpenZeppelin ReentrancyGuard
, because they mint a new ERC721 token and so they both could trigger theonERC721Received
method of a malicious contract. In future development, without this protection, some vulnerabilities could be introduced.