Omniscia Nexera Audit

ERC20CappedMintablePresetUpgradeable Code Style Findings

ERC20CappedMintablePresetUpgradeable Code Style Findings

ERM-01C: Incorrect Assumption of Invocation

Description:

The referenced invocation will continue to apply the cap verification due to the ERC20Upgradeable::_mint function invoking the ERC20Upgradeable::_update function that has been overridden by the ERC20CappedUpgradeable::_update function implementation.

Example:

contracts/ERC20CappedMintablePresetUpgradeable.sol
82/**
83 * @dev Mints multiple values for multiple receivers
84 * @dev Length of `recipients` and `values` arrays should be same
85 */
86function batchMint(address[] calldata recipients, uint256[] calldata values) external onlyRole(MINTER_ROLE) {
87 uint256 recipientsLength = recipients.length;
88 require(recipientsLength == values.length, ArrayLengthMismatch());
89
90 uint256 totalValue = 0;
91 for (uint256 i = 0; i < recipientsLength; i++) {
92 // here we call uncapped version of _mint to prevent cap verification till last recipient is processed
93 ERC20Upgradeable._mint(recipients[i], values[i]);
94 unchecked {
95 // Overflow not possible: totalValue + amount is at most totalSupply + amount, which is checked in `_mint()`.
96 totalValue += values[i];
97 }
98 }
99
100 // Using same error string as in `ERC20CappedUpgradeable._mint()`
101 require(totalSupply() <= cap(), ERC20ExceededCap(totalSupply(), cap()));
102
103 emit BatchMint(_msgSender(), totalValue);
104}

Recommendation:

We advise the code to invoke the ERC20Upgradeable::_update function variant instead, ensuring that cap limitations are properly bypassed in a gas efficient manner.

To note, the function will also have to impose the restriction of the ERC20CappedMintablePresetUpgradeable::_update function as it will no longer be invoked either.

Alleviation:

The code was updated to properly invoke the ERC20Upgradeable::_update variant, ensuring the cap limitation is bypassed efficiently as its documentation details.

ERM-02C: Inefficient Re-Invocation of Getter Functions

Description:

The referenced statement will invoke the ERC20Upgradeable::totalSupply and ERC20CappedUpgradeable::cap functions twice redundantly.

Example:

contracts/ERC20CappedMintablePresetUpgradeable.sol
101require(totalSupply() <= cap(), ERC20ExceededCap(totalSupply(), cap()));

Recommendation:

We advise the result of those calls to be cached to local variables that are consequently re-used, optimizing the statement's error-case gas cost in line with the original ERC20CappedUpgradeable::_update implementation.

Alleviation:

The referenced getter functions are now invoked once, optimizing the code's gas cost.