AI Arena - Fitro'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: 253/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/cd1a0e6d1b40168657d1aaee8223dc050e15f8cc/src/MergingPool.sol#L139-L167 https://github.com/code-423n4/2024-02-ai-arena/blob/cd1a0e6d1b40168657d1aaee8223dc050e15f8cc/src/FighterFarm.sol#L313-L331 https://github.com/code-423n4/2024-02-ai-arena/blob/cd1a0e6d1b40168657d1aaee8223dc050e15f8cc/src/FighterFarm.sol#L33 https://github.com/code-423n4/2024-02-ai-arena/blob/cd1a0e6d1b40168657d1aaee8223dc050e15f8cc/src/FighterFarm.sol#L495

Vulnerability details

Impact

claimRewards() allows to the winners to claim their NFT. However, if the winner owns 10 fighters, they won't be able to claim their rewards, resulting in permanent loss.

Proof of Concept

claimRewards() mint an NFT for the winners is achieved through mintFromMergingPool().

if (msg.sender == winnerAddresses[currentRound][j]) {
    _fighterFarmInstance.mintFromMergingPool(
       msg.sender,
       modelURIs[claimIndex],
       modelTypes[claimIndex],
       customAttributes[claimIndex]
     );
     claimIndex += 1;
}

Subsequently, mintFromMergingPool() invokes _createNewFighter().

function mintFromMergingPool(
    address to, 
    string calldata modelHash, 
    string calldata modelType, 
    uint256[2] calldata customAttributes
) 
    public 
{
        require(msg.sender == _mergingPoolAddress);
        _createNewFighter(
            to, 
            uint256(keccak256(abi.encode(msg.sender, fighters.length))), 
            modelHash, 
            modelType,
            0,
            0,
            customAttributes
        );
}

Within _createNewFighter(), it verifies whether the winner owns fewer than MAX_FIGHTERS_ALLOWED (which is 10); if not, reverse.

uint8 public constant MAX_FIGHTERS_ALLOWED = 10;
require(balanceOf(to) < MAX_FIGHTERS_ALLOWED);

The issue arises because winners are designated by admins for a current roundID using pickWinner(), and this designation can't be altered due to the incrementation of the roundID.

function pickWinner(uint256[] calldata winners) external {
    require(isAdmin[msg.sender]);
    require(winners.length == winnersPerPeriod, "Incorrect number of winners");
    require(!isSelectionComplete[roundId], "Winners are already selected");
    uint256 winnersLength = winners.length;
    address[] memory currentWinnerAddresses = new address[](winnersLength);
    for (uint256 i = 0; i < winnersLength; i++) {
        currentWinnerAddresses[i] = _fighterFarmInstance.ownerOf(winners[i]);
        totalPoints -= fighterPoints[winners[i]];
        fighterPoints[winners[i]] = 0;
     }
     winnerAddresses[roundId] = currentWinnerAddresses;
     isSelectionComplete[roundId] = true;
@>   roundId += 1;
}

If the winner possesses 10 fighters, they cannot claim their reward, and admins are powerless to rectify the situation because the roundID has incremented, rendering it impossible to reset the winners. Consequently, the winners lose their rewards.

Tools Used

Manual review.

Create a function controled by admins to designate winners for a particular roundID.

Assessed type

DoS

#0 - c4-pre-sort

2024-02-22T08:45:00Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-02-22T08:45:08Z

raymondfam marked the issue as duplicate of #216

#2 - c4-judge

2024-03-11T12:49:45Z

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