Platform: Code4rena
Start Date: 09/02/2024
Pot Size: $60,500 USDC
Total HM: 17
Participants: 283
Period: 12 days
Judge:
Id: 328
League: ETH
Rank: 248/283
Findings: 1
Award: $0.23
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ahmedaghadi
Also found by: 0x13, 0xAleko, 0xDetermination, 0xKowalski, 0xPluto, 0xRiO, 0xvj, AlexCzm, Avci, BARW, BigVeezus, Cryptor, DeFiHackLabs, Draiakoo, Fitro, Giorgio, GoSlang, Greed, Honour, Kalogerone, KmanOfficial, Krace, McToady, MidgarAudits, MrPotatoMagic, Nyxaris, ReadyPlayer2, Ryonen, SovaSlava, SpicyMeatball, VAD37, _eperezok, alexzoid, almurhasan, btk, cu5t0mpeo, deadrxsezzz, djxploit, dvrkzy, emrekocak, erosjohn, evmboi32, fnanni, grearlake, inzinko, jesjupyter, jesusrod15, josephdara, ke1caM, klau5, ktg, ladboy233, merlinboii, nuthan2x, peanuts, pipidu83, pontifex, radev_sw, sl1, sobieski, soliditywala, t0x1c, taner2344, vnavascues, y4y, yovchev_yoan, zaevlad
0.2347 USDC - $0.23
Players will not be able to receive the NFTs that they won.
in FighterFarm
contract declares that
MAX_FIGHTERS_ALLOWED = 10;
so , If a successful player participates in a round with different NFTs and earns enough points to win a new NFT, they will not be able to receive the NFTs they won, and the transaction will revert()
Here is scenario :
Bob has 9 fighter NFT's
Bob is very successful player and he takes first two place with his two different NFT's in one round.
at the end of the round, contract owner calls MergingPool::pickWinner(uint256[] calldata winners) and passes Bob's NFT's as a parameter.
Bob calls MergingPool::claimRewards
and as a expected transaction reverts. He couldn't get any NFT because he has exceeding 10 NFT for per address rule.
Bob has lost his 10th NFT’s even though it is allowed to have it...
Bob owns 9 fighter NFTs.
Bob is successful player, Bob secured the first two positions in a round using two different NFTs.
At the round's end, the contract owner calls MergingPool::pickWinner(uint256[] calldata winners)
, including Bob's NFTs as parameters.
Bob calls MergingPool::claimRewards
, but the transaction reverts as expected. He is not able to claim any additional NFTs, he remains capped at the 10 NFT per address limit.
Bob loses his NFT's even though possessing it initially violates the rule.
The issue was classified as High Risk because there is a risk of losing won NFTs and players are experiencing losses.
Here is POC ...
Please add following code to test/MergingPool.t.sol
function testPickWinnerTaner() public { //Bob has 9 fighter to owner _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); _mintFromMergingPool(_ownerAddress); assertEq(_fighterFarmContract.doesTokenExist(0), true); assertEq(_fighterFarmContract.doesTokenExist(1), true); assertEq(_fighterFarmContract.doesTokenExist(2), true); assertEq(_fighterFarmContract.doesTokenExist(3), true); assertEq(_fighterFarmContract.doesTokenExist(4), true); assertEq(_fighterFarmContract.doesTokenExist(5), true); assertEq(_fighterFarmContract.doesTokenExist(6), true); assertEq(_fighterFarmContract.doesTokenExist(7), true); assertEq(_fighterFarmContract.doesTokenExist(8), true); // Bob goes the battle with two different fighters :fighter number 5 and 7 ... // and win the first two titles with his fighters. uint256[] memory _winners = new uint256[](2); _winners[0] = 5; //Bob's fighter number 5 _winners[1] = 7; //Bob's fighter number 7 _mergingPoolContract.pickWinner(_winners); //contract owner picking winners and passing Bob's fighters assertEq(_mergingPoolContract.isSelectionComplete(0), true); assertEq(_mergingPoolContract.winnerAddresses(0, 0) == _ownerAddress, true); //first winner is Bob assertEq(_mergingPoolContract.winnerAddresses(0, 1) == _ownerAddress, true); //second winner is also Bob //preparing reward NFT's string[] memory _modelURIs = new string[](2); _modelURIs[0] = "ipfs://bafybeiaatcgqvzvz3wrjiqmz2ivcu2c5sqxgipv5w2hzy4pdlw7hfox42m"; _modelURIs[1] = "ipfs://bafybeiaatcgqvzvz3wrjiqmz2ivcu2c5sqxgipv5w2hzy4pdlw7hfox42m"; string[] memory _modelTypes = new string[](2); _modelTypes[0] = "original"; _modelTypes[1] = "original"; uint256[2][] memory _customAttributes = new uint256[2][](2); _customAttributes[0][0] = uint256(1); _customAttributes[0][1] = uint256(80); _customAttributes[1][0] = uint256(1); _customAttributes[1][1] = uint256(80); // Bob is trying to claiming rewards but transaction reverts vm.expectRevert(); _mergingPoolContract.claimRewards(_modelURIs, _modelTypes, _customAttributes); }
Manual review, Foundry
Please consider to add checking winning address logic to game.
Context
#0 - c4-pre-sort
2024-02-25T09:04:50Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-02-25T09:05:07Z
raymondfam marked the issue as duplicate of #216
#2 - c4-judge
2024-03-11T12:49:32Z
HickupHH3 changed the severity to 2 (Med Risk)
#3 - c4-judge
2024-03-11T12:53:41Z
HickupHH3 marked the issue as satisfactory