The Neuron.sol contract has a max supply set to 10**18 * 10**9. And the mint function has the following check
function mint(address to, uint256 amount) public virtual {
require(totalSupply() + amount < MAX_SUPPLY, "Trying to mint more than the max supply");
require(hasRole(MINTER_ROLE, msg.sender), "ERC20: must have minter role to mint");
_mint(to, amount);
}
In the RankedBattle.sol contract the NRN rewards for a round are set in the following way:
There are no checks if max supply is reached, and tokens are not directly minted to the contract. There is an initial mint to the treasury for 10**18 * 10**8 * 2 and an initial contributor mint for 10**18 * 10**8 * 5. There is also the possibility that there are airdrops which will increase the supply of NRN tokens. After the initial mints the contract will be left with 10**9 - ((10**8 * 2) +(10**8 * 5)) = 300_000_000. The problem will arise after many rounds, also depends on the amount of NRN tokens allocated for rewards in each round.
The claimNRN() function is implemented in the following way
There are scenarios where a user may not claim his rewards for a couple of rounds and when he decides to do so, the contract can't mint him any rewards, even if he has to receive 100 e18 NRN tokens for round n, and 300 e18 NRN tokens for round n+1. If the contract has already minted all tokens but 300 e18 NRN the claimNRN() function will revert. Also the contract can keep on starting new rounds, when the MAX_SUPPLY is already reached, in this case users will spend gas fees, and risk their NRN tokens to try an win additional NRN tokens, but when they try and claim them it won't be possible as the mint call will revert.
Proof of Concept
Tools Used
Manual review
Recommended Mitigation Steps
When setting up the rewards for each round, consider first having them minted to the RankedBattle.sol contract and then transfer them from the contract to the user when they decide to claim them by calling the claimNRN() function.
Lines of code
https://github.com/code-423n4/2024-02-ai-arena/blob/main/src/RankedBattle.sol#L294-L311
Vulnerability details
Impact
The
Neuron.sol
contract has a max supply set to10**18 * 10**9
. And the mint function has the following checkIn the
RankedBattle.sol
contract the NRN rewards for a round are set in the following way:There are no checks if max supply is reached, and tokens are not directly minted to the contract. There is an initial mint to the treasury for
10**18 * 10**8 * 2
and an initial contributor mint for10**18 * 10**8 * 5
. There is also the possibility that there are airdrops which will increase the supply of NRN tokens. After the initial mints the contract will be left with10**9 - ((10**8 * 2) +(10**8 * 5)) = 300_000_000
. The problem will arise after many rounds, also depends on the amount of NRN tokens allocated for rewards in each round. The claimNRN() function is implemented in the following wayThere are scenarios where a user may not claim his rewards for a couple of rounds and when he decides to do so, the contract can't mint him any rewards, even if he has to receive 100 e18 NRN tokens for round n, and 300 e18 NRN tokens for round n+1. If the contract has already minted all tokens but 300 e18 NRN the claimNRN() function will revert. Also the contract can keep on starting new rounds, when the MAX_SUPPLY is already reached, in this case users will spend gas fees, and risk their NRN tokens to try an win additional NRN tokens, but when they try and claim them it won't be possible as the mint call will revert.
Proof of Concept
Tools Used
Manual review
Recommended Mitigation Steps
When setting up the rewards for each round, consider first having them minted to the
RankedBattle.sol
contract and then transfer them from the contract to the user when they decide to claim them by calling the claimNRN() function.Assessed type
Invalid Validation