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: 65/99
Findings: 2
Award: $80.20
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
48.9769 USDC - $48.98
>= 0
check of uint
variableExplanation: The user should receive the message when totalStaked = 0
require(totalStaked >= 0, 'nothing staked to rage quit');
Change totalStaked >= 0
to totalStaked > 0
/// @dev This is the adress that is used to send auto sniped orders for execution on chain
Change adress
to address
/// @dev Storate variable that keeps track of valid currencies (tokens)
Change Storate
to Storage
either by staking the specified number of tokens for no duration or a less number of tokens but with higher durations.
Change less
to lower
* @notice Untake tokens
Change Untake
to Unstake
(userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);
Suggestion: Change 10**18
to 1e18
10**4
occurs in both lines referenced below:
uint256 PRECISION = 10**4; // precision for division; similar to bps
Suggestion: Change 10**4
to 1e4
in both cases
🌟 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
31.22 USDC - $31.22
Require
message is too longThe revert strings below can be shortened to 32 characters or fewer (as shown) to save gas
require(!isUserOrderNonceExecutedOrCancelled[msg.sender][orderNonces[i]], 'nonce already executed or cancelled');
Change message to nonce already exec or cancelled
require( userstakedAmounts[msg.sender][oldDuration].amount >= amount, 'insufficient staked amount to change duration' );
Change message to insuf stake to change duration
require(newDuration > oldDuration, 'new duration must be greater than old duration');
Change message to new duration must exceed old dur
require
functionSplitting the require()
statement into separate requires
instead of using '&&' saves gas
require(numSells == buys.length && numSells == constructs.length, 'mismatched lengths');
Recommendation:
require(numSells == buys.length, 'mismatched lengths'); require(numSells == constructs.length, 'mismatched lengths');
require(makerOrderValid && executionValid, 'order not verified');
Recommendation:
require(makerOrderValid, 'order not verified'); require(executionValid, 'order not verified');
!= 0
instead of > 0
in a require
statement if variable is an unsigned integer (uint
)!= 0
should be used where possible since > 0
costs more gas
require(numNonces > 0, 'cannot be empty');
Change numNonces > 0
to numNonces != 0
For example, initializing uint
variables to their default value of 0
is unnecessary and costs gas
_isPriceValid
is initialized to false
in both lines below:
bool _isPriceValid = false;
Change to bool _isPriceValid;
in both cases
uint256 numConstructedItems = 0;
Change to uint256 numConstructedItems;
uint256 numTakerItems = 0;
Change to uint256 numTakerItems;
uint256 numCollsMatched = 0;
Change to uint256 numCollsMatched;
uint256 numTokenIdsPerCollMatched = 0;
Change to uint256 numTokenIdsPerCollMatched;
uint256 sum = 0;
Change to uint256 sum;
The for
loop counter (either i
, j
, 'kor
l`) is initialized unnecessarily to zero in the 22 loops referenced below:
Example:
for (uint256 i = 0; i < nftsLength; ) { unchecked { numConstructedItems += constructedNfts[i].tokens.length; ++i; } }
Change uint256 i = 0;
to uint256 i;
Storage of uints or ints smaller than 32 bytes incurs overhead. Solution is to use size of at least 32, then downcast where needed
PROTOCOL_FEE_BPS
, protocolFeeBps
, _protocolFeeBps
, BRONZE_STAKE_THRESHOLD
, SILVER_STAKE_THRESHOLD
, GOLD_STAKE_THRESHOLD
, PLATINUM_STAKE_THRESHOLD
, THREE_MONTH_PENALTY
, SIX_MONTH_PENALTY
, and TWELVE_MONTH_PENALTY
and related variables are initiated as unit16
when they could be set to unit32
and downcast as necessary
#0 - nneverlander
2022-06-22T14:21:01Z
Thank you! Implemented all of these in: https://github.com/infinitydotxyz/exchange-contracts-v2/commit/750695e41a8a58a1ece0cf933ca8440adc184803