Use != 0 instead of > 0 when comparing unsigned integers
!= 0 will do the same as > 0 for unsigned integers, but != 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled.
Instances include :
core/InfinityExchange.sol:392: require(numNonces > 0, 'cannot be empty');
Recommendation
It is recommended to replace > 0 with != 0, as they do the same thing for unsigned integers, and '!= 0' costs less gas compared to > 0 in require statements with the optimizer enabled, also enable the optimizer.
For example :
core/InfinityExchange.sol:392: require(numNonces != 0, 'cannot be empty');
Don't explicitly initialize variables with the default value
Uninitialized variables are assigned with the default value of their type, initializing a variable with its default value costs unnecessary gas.
Instances include :
core/InfinityExchange.sol:148: for (uint256 i = 0; i < numMakerOrders; ) {
core/InfinityExchange.sol:200: for (uint256 i = 0; i < ordersLength; ) {
core/InfinityExchange.sol:219: for (uint256 i = 0; i < ordersLength; ) {
core/InfinityExchange.sol:272: for (uint256 i = 0; i < numSells; ) {
core/InfinityExchange.sol:308: for (uint256 i = 0; i < numMakerOrders; ) {
core/InfinityExchange.sol:349: for (uint256 i = 0; i < ordersLength; ) {
core/InfinityExchange.sol:393: for (uint256 i = 0; i < numNonces; ) {
core/InfinityExchange.sol:1048: for (uint256 i = 0; i < numNfts; ) {
core/InfinityExchange.sol:1086: for (uint256 i = 0; i < numTokens; ) {
core/InfinityExchange.sol:1109: for (uint256 i = 0; i < numNfts; ) {
core/InfinityExchange.sol:1190: for (uint256 i = 0; i < numNfts; ) {
core/InfinityExchange.sol:1206: for (uint256 i = 0; i < numTokens; ) {
core/InfinityOrderBookComplication.sol:76: for (uint256 i = 0; i < ordersLength; ) {
core/InfinityOrderBookComplication.sol:82: for (uint256 j = 0; j < nftsLength; ) {
core/InfinityOrderBookComplication.sol:197: uint256 numConstructedItems = 0;
core/InfinityOrderBookComplication.sol:199: for (uint256 i = 0; i < nftsLength; ) {
core/InfinityOrderBookComplication.sol:214: uint256 numTakerItems = 0;
core/InfinityOrderBookComplication.sol:216: for (uint256 i = 0; i < nftsLength; ) {
core/InfinityOrderBookComplication.sol:244: uint256 numCollsMatched = 0;
core/InfinityOrderBookComplication.sol:246: for (uint256 i = 0; i < order2NftsLength; ) {
core/InfinityOrderBookComplication.sol:247: for (uint256 j = 0; j < order1NftsLength; ) {
core/InfinityOrderBookComplication.sol:289: uint256 numTokenIdsPerCollMatched = 0;
core/InfinityOrderBookComplication.sol:290: for (uint256 k = 0; k < item2TokensLength; ) {
core/InfinityOrderBookComplication.sol:291: for (uint256 l = 0; l < item1TokensLength; ) {
core/InfinityOrderBookComplication.sol:318: uint256 sum = 0;
core/InfinityOrderBookComplication.sol:320: for (uint256 i = 0; i < ordersLength; ) {
MockERC721.sol:11: for (uint256 i = 0; i < 100; i++) {
Recommendation
It is recommended to initialize variables without assigning them the default value, for example :
If possible, use bitwise shift instead of division/multiplication
If the divisor/multiplier x is a power of 2, it can be calculated by shifting log2(x) to the right/left. Division with / cost more gas compared to bitwise shifting.
It is recommended to replace / and * with >> and << respectively and divisor/multiplier x to log2(x), for division/multiplication where the divisor/multiplier is a power of 2, for example :
If possible, use prefix increment instead of postfix increment
Prefix increment ++i returns the updated value after it's incremented and postfix increment i++ returns the original value then increments it. Prefix increment costs less gas compared to postfix increment.
Instances includes :
MockERC721.sol:11: for (uint256 i = 0; i < 100; i++) {
MockERC721.sol:12: _safeMint(msg.sender, numMints++);
Recommendation
It is recommended to use prefix increment instead of postfix one when the return value is not needed, as both of them will give the same result and prefix increment costs less gas.
For example :
MockERC721.sol:11: for (uint256 i = 0; i < 100; ++i) {
Don't use long revert strings
Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
Instances includes :
core/InfinityExchange.sol:395: require(!isUserOrderNonceExecutedOrCancelled[msg.sender][orderNonces[i]], 'nonce already executed or cancelled');
staking/InfinityStaker.sol:96: require(newDuration > oldDuration, 'new duration must be greater than old duration');
Recommendation
It is recommended to use error code and providing a reference to the error code instead of a long revert string., for example :
// Link to the reference of error codes
staking/InfinityStaker.sol:96: require(newDuration > oldDuration, 'ERR');
Public function could be declared external
Public functions that are never called by the contract should be declared external to save gas.
Instances includes :
renounceOwnership() should be declared external:
- Ownable.renounceOwnership() (node_modules/@openzeppelin/contracts/access/Ownable.sol#54-56)
transferOwnership(address) should be declared external:
- Ownable.transferOwnership(address) (node_modules/@openzeppelin/contracts/access/Ownable.sol#62-65)
balanceOf(address) should be declared external:
- ERC721.balanceOf(address) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#62-65)
name() should be declared external:
- ERC721.name() (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#79-81)
symbol() should be declared external:
- ERC721.symbol() (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#86-88)
approve(address,uint256) should be declared external:
- ERC721.approve(address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#112-122)
setApprovalForAll(address,bool) should be declared external:
- ERC721.setApprovalForAll(address,bool) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#136-138)
transferFrom(address,address,uint256) should be declared external:
- ERC721.transferFrom(address,address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#150-159)
safeTransferFrom(address,address,uint256) should be declared external:
- ERC721.safeTransferFrom(address,address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#164-170)
getUserTotalStaked(address) should be declared external:
- InfinityStaker.getUserTotalStaked(address) (contracts/staking/InfinityStaker.sol#154-160)
getUserTotalVested(address) should be declared external:
- InfinityStaker.getUserTotalVested(address) (contracts/staking/InfinityStaker.sol#167-173)
Recommendation
Use the external attribute for functions never called from the contract.
Use != 0 instead of > 0 when comparing unsigned integers
!= 0 will do the same as > 0 for unsigned integers, but != 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled.
Instances include :
Recommendation
It is recommended to replace
> 0
with!= 0
, as they do the same thing for unsigned integers, and '!= 0' costs less gas compared to> 0
in require statements with the optimizer enabled, also enable the optimizer.For example :
Don't explicitly initialize variables with the default value
Uninitialized variables are assigned with the default value of their type, initializing a variable with its default value costs unnecessary gas.
Instances include :
Recommendation
It is recommended to initialize variables without assigning them the default value, for example :
If possible, use bitwise shift instead of division/multiplication
If the divisor/multiplier
x
is a power of 2, it can be calculated by shiftinglog2(x)
to the right/left. Division with/
cost more gas compared to bitwise shifting.Instances include :
Recommendation
It is recommended to replace
/
and*
with>>
and<<
respectively and divisor/multiplierx
tolog2(x)
, for division/multiplication where the divisor/multiplier is a power of 2, for example :If possible, use prefix increment instead of postfix increment
Prefix increment
++i
returns the updated value after it's incremented and postfix incrementi++
returns the original value then increments it. Prefix increment costs less gas compared to postfix increment.Instances includes :
Recommendation
It is recommended to use prefix increment instead of postfix one when the return value is not needed, as both of them will give the same result and prefix increment costs less gas.
For example :
Don't use long revert strings
Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
Instances includes :
Recommendation
It is recommended to use error code and providing a reference to the error code instead of a long revert string., for example :
Public function could be declared external
Public functions that are never called by the contract should be declared external to save gas.
Instances includes :
Recommendation
Use the external attribute for functions never called from the contract.