AI Arena - GoSlang's results

In AI Arena you train an AI character to battle in a platform fighting game. Imagine a cross between Pokémon and Super Smash Bros, but the characters are AIs, and you can train them to learn almost any skill in preparation for battle.

General Information

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

AI Arena

Findings Distribution

Researcher Performance

Rank: 256/283

Findings: 1

Award: $0.23

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2024-02-ai-arena/blob/main/src/MergingPool.sol#L139-L167 https://github.com/code-423n4/2024-02-ai-arena/blob/main/src/RankedBattle.sol#L244-L265 https://github.com/code-423n4/2024-02-ai-arena/blob/main/src/MergingPool.sol#L172-L185

Vulnerability details

Impact

claimRewards, claimNRN and getUnclaimedRewards are implemented in a way where we have to loop over every single round and check if the currentOwner of the tokenId is the winner of each round. A problem arises when doing it like this since inactive users can come back after a potentially long time or new users can obtain fighters as well. This will result in large gas fees and a potential DoS for calling claimRewards for any new user.

Proof of Concept

function getUnclaimedRewards(address claimer) external view returns(uint256) { uint256 winnersLength; uint256 numRewards = 0; uint32 lowerBound = numRoundsClaimed[claimer]; for (uint32 currentRound = lowerBound; currentRound < roundId; currentRound++) { winnersLength = winnerAddresses[currentRound].length; for (uint32 j = 0; j < winnersLength; j++) { if (claimer == winnerAddresses[currentRound][j]) { numRewards += 1; } } } return numRewards; }
function stakeNRN(uint256 amount, uint256 tokenId) external { require(amount > 0, "Amount cannot be 0"); require(_fighterFarmInstance.ownerOf(tokenId) == msg.sender, "Caller does not own fighter"); require(_neuronInstance.balanceOf(msg.sender) >= amount, "Stake amount exceeds balance"); require(hasUnstaked[tokenId][roundId] == false, "Cannot add stake after unstaking this round"); _neuronInstance.approveStaker(msg.sender, address(this), amount); bool success = _neuronInstance.transferFrom(msg.sender, address(this), amount); if (success) { if (amountStaked[tokenId] == 0) { _fighterFarmInstance.updateFighterStaking(tokenId, true); } amountStaked[tokenId] += amount; globalStakedAmount += amount; stakingFactor[tokenId] = _getStakingFactor( tokenId, _stakeAtRiskInstance.getStakeAtRisk(tokenId) ); _calculatedStakingFactor[tokenId][roundId] = true; emit Staked(msg.sender, amount); } }
function claimRewards( string[] calldata modelURIs, string[] calldata modelTypes, uint256[2][] calldata customAttributes ) external { uint256 winnersLength; uint32 claimIndex = 0; uint32 lowerBound = numRoundsClaimed[msg.sender]; for (uint32 currentRound = lowerBound; currentRound < roundId; currentRound++) { numRoundsClaimed[msg.sender] += 1; winnersLength = winnerAddresses[currentRound].length; for (uint32 j = 0; j < winnersLength; j++) { if (msg.sender == winnerAddresses[currentRound][j]) { _fighterFarmInstance.mintFromMergingPool( msg.sender, modelURIs[claimIndex], modelTypes[claimIndex], customAttributes[claimIndex] ); claimIndex += 1; } } } if (claimIndex > 0) { emit Claimed(msg.sender, claimIndex); } }

Tools Used

vscode

Keep that of rounds users participated in separably or allow users to loop over x amount of rounds per call.

Assessed type

DoS

#0 - c4-pre-sort

2024-02-24T08:27:01Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-02-24T08:28:06Z

raymondfam marked the issue as duplicate of #1541

#2 - c4-judge

2024-03-11T13:00:21Z

HickupHH3 marked the issue as duplicate of #216

#3 - c4-judge

2024-03-11T13:08:05Z

HickupHH3 changed the severity to 2 (Med Risk)

#4 - c4-judge

2024-03-12T02:37:22Z

HickupHH3 marked the issue as partial-50

#5 - c4-judge

2024-03-21T02:06:17Z

HickupHH3 marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter