The overflow vulnerability in mintBatch represents a medium severity issue due to the access restriction, but it still poses risks for token distribution reliability and potential supply inflation.
The mintBatch function in the contract allows authorized minters to mint multiple token types in a single transaction by passing arrays of ids and amounts. However, when extremely large values are passed into the amounts array, the function encounters an arithmetic overflow in the internal _mintBatch function, which can lead to incorrect token balances or total supply calculations.
Overflow may cause the contract to mint more tokens than intended, potentially inflating the token supply or violating tokenomics constraints.
I have created the following POC and then run forge test --fuzz-runs 2 i.e. 2 times and the output resulted in arithmetic overflow.
/ SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import "forge-std/Test.sol";
import "../src/OWPIdentity.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract OWPIdentityTest is Test {
OWPIdentity owp;
address defaultAdmin;
address minter;
function setUp() public {
defaultAdmin = address(0xABCD);
minter = address(0xDEAD);
owp = new OWPIdentity(defaultAdmin, minter, "https://example.com/metadata/");
vm.startPrank(defaultAdmin);
owp.setURI("https://example.com/updated_metadata/");
vm.stopPrank();
}
function testFuzzMintBatch(address to, uint256[] memory ids, uint256[] memory amounts) public {
vm.assume(to != address(0));
vm.assume(ids.length == amounts.length);
vm.startPrank(minter);
owp.mintBatch(to, ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
require(ids[i] > 0, "Token ID must be positive");
uint256 tokenSupply = owp.totalSupply(ids[i]);
require(tokenSupply + amounts[i] <= type(uint256).max, "Overflow detected");
}
owp.burnBatchMultiple(createAddressArray(ids.length, to), ids, amounts);
for (uint256 i = 0; i < ids.length; i++) {
assertEq(owp.balanceOf(to, ids[i]), 0, "Batch burn amount not correct");
}
vm.stopPrank();
}
function createAddressArray(uint256 length, address value) internal pure returns (address[] memory) {
address[] memory array = new address[]();
for (uint256 i = 0; i < length; i++) {
array[i] = value;
}
return array;
}
}
Add validation to ensure that values in ids and amounts do not exceed expected limits
function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
public
onlyRole(MINTER_ROLE)
{
require(ids.length == amounts.length, "Mismatched ids and amounts length");
for (uint256 i = 0; i < amounts.length; i++) {
require(amounts[i] > 0, "Amount must be greater than zero");
require(amounts[i] <= MAX_MINT_AMOUNT, "Amount exceeds maximum allowed");
}
_mintBatch(to, ids, amounts, data);
}