Platform: Code4rena
Start Date: 14/06/2022
Pot Size: $50,000 USDC
Total HM: 19
Participants: 99
Period: 5 days
Judge: HardlyDifficult
Total Solo HM: 4
Id: 136
League: ETH
Rank: 34/99
Findings: 3
Award: $201.29
π Selected for report: 0
π Solo Findings: 0
π Selected for report: WatchPug
Also found by: BowTiedWardens, GreyArt, Ruhum, berndartmueller, cccz, csanuragjain, defsec, joestakey, m9800, peritoflores, reassor, shenwilly, throttle, zer0dot
21.1924 USDC - $21.19
https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1266-L1269 https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L725-L726 https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L775-L776 https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L819-L820 https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L873-L874 https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1135-L1136
Contract InfinityExchange.sol
charges protocol fee through PROTOCOL_FEE_BPS
. The issue is that owner of the contract is able to change protocol fee at any time without any restriction which puts him in a very privileged position and allows him to steal user's funds via front-running attack by increasing protocol fee to 100%
.
Exploit Scenario:
matchOneToOneOrders
PROTOCOL_FEE_BPS
to 100%
through setProtocolFee
.setProtocolFee
is being included before matchOneToOneOrders
100%
_execMatchOneToOneOrders
the remainingAmount
sent to seller is 0
and protocol takes all the funds in form of protocol fee.uint256 protocolFee = (protocolFeeBps * execPrice) / 10000; uint256 remainingAmount = execPrice - protocolFee;
This issue is also relevant in case of owner not being a malicious actor. User accepts some kind of protocol fee for example 2.5%
. Then owner just changes the fee to 5%
. User didn't expect that change and effectively lost funds.
_execMatchToOneOrders
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L725-L726_execMatchOneMakerSellToManyMakerBuys
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L775-L776_execMatchOneMakerBuyToManyMakerSells
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L819-L820_execMatchOrders
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L873-L874_transferFees
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1135-L1136Manual Review / VSCode
It is recommended to add additional parameter to sell - accepted protocol fee (similar to a slippage on a dex) and revert transaction if the fee is higher than the one accepted by user. In addition it is recommended to add validation to setProtocolFee
so passed _protocolFeeBps
cannot exceed hardcoded value e.g. 5%
. The final improvement is adding timelock for updating fee through setProtocolFee
.
#0 - nneverlander
2022-06-22T11:01:35Z
Assessment medium since this assumes mal intent on admin.
#1 - HardlyDifficult
2022-07-10T21:13:19Z
π Selected for report: joestakey
Also found by: 0x1f8b, 0x29A, 0x52, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 0xkowloon, 0xmint, 8olidity, BowTiedWardens, Chom, Cityscape, Czar102, ElKu, FSchmoede, Funen, GimelSec, GreyArt, IllIllI, KIntern, Kaiziron, Kenshin, Lambda, MadWookie, MiloTruck, PPrieditis, Picodes, Ruhum, Sm4rty, StErMi, TerrierLover, TomJ, Treasure-Seeker, VAD37, WatchPug, Wayne, _Adam, a12jmx, abhinavmir, antonttc, apostle0x01, asutorufos, berndartmueller, cccz, cloudjunky, codexploder, cryptphi, csanuragjain, defsec, delfin454000, fatherOfBlocks, georgypetrov, hake, hansfriese, horsefacts, hyh, k, kenta, nxrblsrpr, oyc_109, peritoflores, rajatbeladiya, reassor, rfa, robee, sach1r0, saian, samruna, shenwilly, simon135, sorrynotsorry, sseefried, throttle, unforgiven, wagmi, zzzitron
145.524 USDC - $145.52
>=
instead of >
Low
Function InfinityStaker.getRageQuitAmounts
uses require statement to check if uint256
variable totalStaked
is bigger or equal to 0
.
193: require(totalStaked >= 0, 'nothing staked to rage quit');
The check should be verifying if totalStaked
is bigger than 0
- >
.
staking/InfinityStaker.so:193 require(totalStaked >= 0, 'nothing staked to rage quit');
Manual Review / VSCode
It is recommended to change the require
check to:
193: require(totalStaked > 0, 'nothing staked to rage quit');
Low
Multiple contracts do not check for zero addresses which might lead to loss of funds, failed transactions and can break the protocol functionality.
InfinityStaker.sol
:
_tokenAddress
and _infinityTreasury
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L49destination
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L345_infinityTreasury
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L375InfinityExchange.sol
:
_WETH
, _matchExecutor
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L104to
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L371destination
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1221destination
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1229_currency
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1235_complication
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1240_matchExecutor
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1255InfinityToken.sol
:
admin
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/token/InfinityToken.sol#L38Manual Review / VSCode
It is recommended to add zero address checks for listed parameters.
Low
Multiple contracts are not implementing events for critical functions. Lack of events makes it difficult for off-chain applications to monitor the protocol.
InfinityExchange.sol
:
rescueTokens
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1220-L1226rescureETH
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1229-L1232addCurrency
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1235-L1237addComplication
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1240-L1242removeCurrency
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1245-L1247removeComplication
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1250-L1252updateMatchExecutor
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1255-L1257InfinityStaker.sol
:
updateStakeLevelThreshold
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L351-L361updatePenalities
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L364-L372updateInfinityTreasury
function event - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L375-L377Manual Review / VSCode
It is recommended to add missing events to listed functions.
Low
Changing critical addresses such as ownership should be a two-step process where the first transaction (from the old/current address) registers the new address (i.e. grants ownership) and the second transaction (from the new address) replaces the old address with the new one. This gives an opportunity to recover from incorrect addresses mistakenly used in the first step. If not, contract functionality might become inaccessible.
InfinityStaker.sol
Ownable
inheritance - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L15InfinityExchange.sol
Ownable
inheritance - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L50InfinityOrderBookComplication.sol
:
Ownable
inheritance - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L14Manual Review / VSCode
It is recommended to implement two-step process for changing critical addresses.
Non-Critical
Defining big numbers that consists of many digits or performing additional math calculations might lead to accidential errors and mistakes.
core/InfinityExchange.sol:1161: uint256 PRECISION = 10**4; // precision for division; similar to bps core/InfinityOrderBookComplication.sol:338: uint256 PRECISION = 10**4; // precision for division; similar to bp staking/InfinityStaker.sol:237: (userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);
Manual Review / VSCode
It is recommended to use scientific notation.
Non-Critical
Events should index addresses which helps off-chain applications in monitoring the protocol.
core/InfinityExchange.sol:80: event CancelAllOrders(address user, uint256 newMinNonce); core/InfinityExchange.sol:81: event CancelMultipleOrders(address user, uint256[] orderNonces); core/InfinityExchange.sol:82: event NewWethTransferGasUnits(uint32 wethTransferGasUnits); core/InfinityExchange.sol:83: event NewProtocolFee(uint16 protocolFee); --- core/InfinityExchange.sol:85: event MatchOrderFulfilled( bytes32 sellOrderHash, bytes32 buyOrderHash, address seller, address buyer, address complication, // address of the complication that defines the execution address currency, // token address of the transacting currency uint256 amount // amount spent on the order ); --- core/InfinityExchange.sol:95: event TakeOrderFulfilled( bytes32 orderHash, address seller, address buyer, address complication, // address of the complication that defines the execution address currency, // token address of the transacting currency uint256 amount // amount spent on the order ); --- staking/InfinityStaker.sol:44: event Staked(address indexed user, uint256 amount, Duration duration); staking/InfinityStaker.sol:45: event DurationChanged(address indexed user, uint256 amount, Duration oldDuration, Duration newDuration); staking/InfinityStaker.sol:46: event UnStaked(address indexed user, uint256 amount); staking/InfinityStaker.sol:47: event RageQuit(address indexed user, uint256 totalToUser, uint256 penalty); token/TimelockConfig.sol:34: event ChangeRequested(bytes32 configId, uint256 value); token/TimelockConfig.sol:35: event ChangeConfirmed(bytes32 configId, uint256 value); token/TimelockConfig.sol:36: event ChangeCanceled(bytes32 configId, uint256 value); token/InfinityToken.sol:35: event EpochAdvanced(uint256 currentEpoch, uint256 supplyMinted);
Manual Review / VSCode
It is recommended to add indexing to address
type parameters.
Non-Critical
Contracts are missing natspec comments which makes code more difficult to read and prone to errors.
InfinityExchange.sol
:
@param _WETH
and @param _matchExecutor
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L104@return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L533@return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L538@return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L543@return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L548@param index
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L553@param currency
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L558@param order
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1153@param order
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1168@param destination
, @param currencyand
@param amount` - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1220@param destination
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1229@param _currency
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1235@param _complication
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1240@param _currency
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1245@param _complication
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1250@param _matchExecutor
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1255@param _wethTransferGasUnits
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1260@param _protocolFeeBps
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1266InfinityOrderBookComplication.sol
:
@param sell
, @param buy
, @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L168-L169@param sell
, @param buy
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L182@param sell
, @param buy,
@param constructedNftsand
@return` - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L191-L192@param makeOrder
, @param takerItems
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L208-L209@param orders
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L316-L317@param order
and @return
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityOrderBookComplication.sol#L329-L330InfinityStaker.sol
:
@param _tokenAddress
and @param _infinityTreasury
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L49@param user
, @param amount
, @param noVesting
, @param vestedThreeMonths
, @param vestedSixMonths
, @param vestedTwelveMonths
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L287-L290@param user
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L327-L328@param destination
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L344-L345@param stakeLevel
, @param threshold
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L350-L351@param threeMonthPenalty
, @param sixMonthPenalty
, @param twelveMonthPenalty
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L363-L364@param _infinityTreasury
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L374-L375InfinityToken.sol
:
TimelockConfig.sol
:
Manual Review / VSCode
It is recommended to add missing natspec comments.
Non-Critical
Code and comments contain typos which makes code more difficult to read and prone to errors.
InfinityStaker.sol
:
Untake tokens
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L112vestedsixMonth
, expected camel case vestedSixMonths
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L120Manual Review / VSCode
It is recommended to correct listed typos.
Non-Critical
Multiple contracts do not check for return values of executed functions. This might lead to accidents and errors since the created transaction is valid but the underlying code did not execute properly.
InfinityExchange.sol
:
_currencies.add
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1236_complications.add
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1241_currencies.remove
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1246_complications.remove
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/core/InfinityExchange.sol#L1251InfinityToken.sol
:
_configSet.add
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/token/TimelockConfig.sol#L55_configSet.add
- https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/token/TimelockConfig.sol#L67Manual Review / VSCode
It is recommended to check the return values of executed functions.
#0 - nneverlander
2022-06-22T14:46:17Z
Thank you
#1 - HardlyDifficult
2022-07-10T21:08:47Z
#2 - HardlyDifficult
2022-07-10T21:11:10Z
#3 - HardlyDifficult
2022-07-10T21:15:10Z
π Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xAsm0d3us, 0xDjango, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xkowloon, BowTiedWardens, Chom, ElKu, FSchmoede, Funen, GimelSec, Kaiziron, Kenshin, Lambda, MadWookie, MiloTruck, PPrieditis, Picodes, PwnedNoMore, StErMi, Tadashi, TerrierLover, TomJ, Tomio, Wayne, Waze, _Adam, antonttc, apostle0x01, asutorufos, c3phas, codexploder, defsec, delfin454000, fatherOfBlocks, hake, hansfriese, hyh, joestakey, k, kenta, oyc_109, peritoflores, reassor, rfa, robee, sach1r0, simon135, slywaters, zer0dot
34.5799 USDC - $34.58
Function InfinityStaker.getRageQuitAmounts
uses require statement to check if uint256
variable totalStaked
is bigger or equal to 0
. Variable of type uint256
is always bigger or equal to 0
which makes this check completely obsolete.
staking/InfinityStaker.so:193 require(totalStaked >= 0, 'nothing staked to rage quit');
Manual Review / VSCode
It is recommended to remove obsolete check or change it to check if totalStaked
value is bigger >
than 0
.
Multiple contracts are using math exponent calculation to express big numbers. This consumes additional gas and its better to use scienfic notation.
core/InfinityOrderBookComplication.sol:338: uint256 PRECISION = 10**4; // precision for division; similar to bps core/InfinityExchange.sol:1161: uint256 PRECISION = 10**4; // precision for division; similar to bps staking/InfinityStaker.sol:237: (userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);
Manual Review / VSCode
It is recommended to use scientific notation, for example: 1e18
.
Shortening revert error messages to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
core/InfinityExchange.sol:399: require(!isUserOrderNonceExecutedOrCancelled[msg.sender][orderNonces[i]], 'nonce already executed or cancelled'); -- staking/InfinityStaker.sol:92: require( userstakedAmounts[msg.sender][oldDuration].amount >= amount, 'insufficient staked amount to change duration' ); -- staking/InfinityStaker.sol:96: require(newDuration > oldDuration, 'new duration must be greater than old duration');
Manual Review / VSCode
It is recommended to decrease revert messages to maximum 32 bytes. Alternatively custom error types should be used.
Usage of custom errors reduces the gas cost.
Contracts that should be using custom errors:
InfinityExchange.sol
InfinityOrderBookComplication.sol
InfinityStaker.sol
InfinityToken.sol
TimelockConfig.sol
Manual Review / VSCode
It is recommended to add custom errors to listed contracts.
If a variable is not set/initialized, it is assumed to have the default value (0
for uint, false
for bool, address(0)
for addresses). Explicitly initializing it with its default value is an anti-pattern and waste of gas.
core/InfinityOrderBookComplication.sol:42: bool _isPriceValid = false; core/InfinityOrderBookComplication.sol:108: bool _isPriceValid = false; 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; ) { 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; ) {
Manual Review / VSCode
It is recommended to remove explicit initializations with default values.
When dealing with unsigned integer types, comparisons with != 0
are cheaper than with > 0
.
core/InfinityExchange.sol:392: require(numNonces > 0, 'cannot be empty');
Manual Review / VSCode
It is recommended to use != 0
instead of > 0
.
Packing integer variables into storage slots saves gas.
InfinityStaker.sol
:
17 struct StakeAmount { 18 uint256 amount; 19 uint256 timestamp; 20 }
Manual Review / VSCode
If amount
is not expected to reach specific values it is recommended to pack it in 192 bits
and use 64 bits
for timestamp.
17 struct StakeAmount { 18 uint192 amount; 19 uint64 timestamp; 20 }
Functions declared as public that are never called internally within the contract should be marked as external in order save gas (especially in the case where the function takes arguments, since external functions can read arguments directly from calldata instead of allocating memory).
InfinityStaker.sol
:
getUserTotalStaked
can be set as external - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L154getUserTotalVested
can be set as external - https://github.com/code-423n4/2022-06-infinity/blob/765376fa238bbccd8b1e2e12897c91098c7e5ac6/contracts/staking/InfinityStaker.sol#L167Manual Review / VSCode
It is recommended to change all public functions that are not called internally to external visibility.