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: 48/99
Findings: 2
Award: $86.69
🌟 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
49.5589 USDC - $49.56
address(0x0)
when assigning values to address state variables1. File: InfinityStaker.sol#L50-51
INFINITY_TOKEN = _tokenAddress; INFINITY_TREASURY = _infinityTreasury;
2. File: InfinityStaker.sol#L376
INFINITY_TREASURY = _infinityTreasury;
3. File: InfinityExchange.sol#L115-116
WETH = _WETH; MATCH_EXECUTOR = _matchExecutor;
whenNotPause
modifier on rageQuit()
whenNotPause
similar to unstake()
. If the contract is paused an exploiter could still potentially drain the contract.1. File: InfinityStaker.sol#L136
1. File: InfinityStaker.sol#L237
(userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);
3. File: InfinityExchange.sol#L775
require(minNonce < userMinOrderNonce[msg.sender] + 1000000, 'too many');
3. File: InfinityExchange.sol#L775
uint256 protocolFee = (protocolFeeBps * execPrice) / 10000;
4. File: InfinityExchange.sol#L819
uint256 protocolFee = (protocolFeeBps * execPrice) / 10000;
5. File: InfinityExchange.sol#L1135
uint256 protocolFee = (PROTOCOL_FEE_BPS * amount) / 10000;
1. File: InfinityStaker.sol#L44
event Staked(address indexed user, uint256 amount, Duration duration);
2. File: InfinityStaker.sol#L45
event DurationChanged(address indexed user, uint256 amount, Duration oldDuration, Duration newDuration);
3. File: InfinityStaker.sol#L47
event RageQuit(address indexed user, uint256 totalToUser, uint256 penalty);
updatePenalties()
1. File: InfinityStaker.sol#L364
updateStakeLevelThreshold()
🌟 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
37.1281 USDC - $37.13
In this instance WETH_TRANSFER_GAS_UNITS is already cached as wethTransferGasUnits but wasn't used.
1. File: InfinityExchange.sol#L231
uint256 gasCost = (startGas - gasleft() + WETH_TRANSFER_GAS_UNITS) * tx.gasprice;
cache userMinOrderNonce[msg.sender]
2. File: InfinityExchange.sol#L380-381
require(minNonce > userMinOrderNonce[msg.sender], 'nonce too low'); require(minNonce < userMinOrderNonce[msg.sender] + 1000000, 'too many');
cache userMinOrderNonce[msg.sender] before for loop
3. File: InfinityExchange.sol#L394
require(orderNonces[i] >= userMinOrderNonce[msg.sender], 'nonce too low');
The bronze, silver, and gold threshold variables are each read twice. Caching them will make the function on average cheaper.
4. File: InfinityStaker.sol#L213-223
if (totalPower <= BRONZE_STAKE_THRESHOLD) { return StakeLevel.NONE; } else if (totalPower > BRONZE_STAKE_THRESHOLD && totalPower <= SILVER_STAKE_THRESHOLD) { return StakeLevel.BRONZE; } else if (totalPower > SILVER_STAKE_THRESHOLD && totalPower <= GOLD_STAKE_THRESHOLD) { return StakeLevel.SILVER; } else if (totalPower > GOLD_STAKE_THRESHOLD && totalPower <= PLATINUM_STAKE_THRESHOLD) { return StakeLevel.GOLD; } else { return StakeLevel.PLATINUM; }
1. File: InfinityStaker.sol#L25
address public INFINITY_TOKEN;
The amount variable is checked to be less than or equal to the balance of the staker in each function. This means when performing math with an amount you know it will never overflow/underflow. You can enclose each of these statements in an unchecked{}.
1. File: InfinityStaker.sol#L71
userstakedAmounts[msg.sender][duration].amount += amount;
2. File: InfinityStaker.sol#L99-100
userstakedAmounts[msg.sender][oldDuration].amount -= amount; userstakedAmounts[msg.sender][newDuration].amount += amount;
2. File: InfinityStaker.sol#L156-159 )
userstakedAmounts[user][Duration.NONE].amount + userstakedAmounts[user][Duration.THREE_MONTHS].amount + userstakedAmounts[user][Duration.SIX_MONTHS].amount + userstakedAmounts[user][Duration.TWELVE_MONTHS].amount;
3. File: InfinityStaker.sol#L234-237
((userstakedAmounts[user][Duration.NONE].amount * 1) + (userstakedAmounts[user][Duration.THREE_MONTHS].amount * 2) + (userstakedAmounts[user][Duration.SIX_MONTHS].amount * 3) + (userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);
4. File: InfinityStaker.sol#L314
userstakedAmounts[user][Duration.TWELVE_MONTHS].amount -= amount;
5. File: InfinityStaker.sol#L317
userstakedAmounts[user][Duration.SIX_MONTHS].amount -= amount;
6. File: InfinityStaker.sol#L320
userstakedAmounts[user][Duration.THREE_MONTHS].amount -= amount;
7. File: InfinityStaker.sol#L323
userstakedAmounts[user][Duration.NONE].amount -= amount;
1. File: InfinityExchange.sol#L138-139
require(msg.sender == MATCH_EXECUTOR, 'OME'); require(numMakerOrders == makerOrders2.length, 'mismatched lengths');
2. File: InfinityExchange.sol#L263-264
require(msg.sender == MATCH_EXECUTOR, 'OME'); require(numSells == buys.length && numSells == constructs.length, 'mismatched lengths');
Consider changing these error string to something shorter than 32 bytes.
1. File: InfinityStaker.sol#L92-95
require( userstakedAmounts[msg.sender][oldDuration].amount >= amount, 'insufficient staked amount to change duration' );
2. File: InfinityStaker.sol#L96
require(newDuration > oldDuration, 'new duration must be greater than old duration');