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: 9/99
Findings: 4
Award: $1,303.59
π Selected for report: 1
π Solo Findings: 0
π Selected for report: KIntern
Also found by: GimelSec, csanuragjain, kenzo, unforgiven
607.7909 USDC - $607.79
sell.constraint[0], representing the max number of nft items, can be simply bypassed due to a missing condition. Hence order will process more nft than max limit and hence would cause loss to seller whose nft would be traded without his permission
sell has set constraint[0] as 2 (max number of item allowed) buy has set constraint[0] as 1 (min number of item allowed)
Now canExecMatchOrder is called to check Order validity with constructedNFTs as {A,B,C}
areNumItemsValid function is called which makes below check:
return numConstructedItems >= buy.constraints[0] && buy.constraints[0] <= sell.constraints[0];
This will return true since 3>=1 && 1<=2
But this is incorrect since this order is simply bypassing the sell order max nft constraint which was 2. With this order processed, all 3 nfts will be processed even though only 2 should have been allowed
Add a condition to verify that constructed nft items are not larger than sell constraints
return numConstructedItems >= buy.constraints[0] && buy.constraints[0] <= sell.constraints[0] && numConstructedItems<= sell.constraints[0];
#0 - nneverlander
2022-06-22T11:24:19Z
#1 - nneverlander
2022-07-05T11:15:11Z
#2 - nneverlander
2022-07-05T11:15:23Z
#3 - nneverlander
2022-07-05T11:15:34Z
#4 - HardlyDifficult
2022-07-10T15:15:19Z
π 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/main/contracts/core/InfinityExchange.sol#L1266
There is no max cap on the fees in setProtocolFee function. Admin can have fees as 100_00 which is 100%. Now _transferFees function will make sure that seller gets nothing as remainingAmount becomes 0 and contract will get the whole amount.
Owner calls setProtocolFee and set _protocolFeeBps as 100_00 which is 100%
Now whenever NFT are transferred, _transferFees is called
This calculates the fees over the amount. Since fees is 100% so contract receives full amount and seller receives 0 amount
Set a max fee cap on PROTOCOL_FEE_BPS so that only reasonable fees is deducted
function setProtocolFee(uint16 _protocolFeeBps) external onlyOwner { require(_protocolFeeBps<=MAX_FEES, "Exceeded max fees"); PROTOCOL_FEE_BPS = _protocolFeeBps; emit NewProtocolFee(_protocolFeeBps); }
#0 - nneverlander
2022-06-23T11:24:38Z
Duplicate
#1 - HardlyDifficult
2022-07-11T00:04:39Z
π Selected for report: csanuragjain
Also found by: KIntern
625.2993 USDC - $625.30
canExecMatchOrder is having an incorrect check which makes a valid order as invalid. doItemsIntersect function is also checked on sell.nfts, buy.nfts which is incorrect. doItemsIntersect should only be checked in reference to constructedNfts
Assume buy has nfts {A,B,C}, sell has nft {A,B}, constructedNfts has nft {A}, buy.constraints[0]/sell.constraints[0]/numConstructedItems is 1
Ideally this order should match since constructedNfts {A} is present in both buy and sell
But this will not match since doItemsIntersect(sell.nfts, buy.nfts) will fail because of item C which is not present in sell
Remove doItemsIntersect(sell.nfts, buy.nfts) from InfinityOrderBookComplication.sol#L140
#0 - nneverlander
2022-06-22T11:22:11Z
#1 - HardlyDifficult
2022-07-10T22:41:19Z
Some orders that should be matched would revert. Lowering this to Medium risk.
π 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.3112 USDC - $49.31
https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L364
In updatePenalties function, THREE_MONTH_PENALTY/SIX_MONTH_PENALTY/TWELVE_MONTH_PENALTY are not having any upper bound, nor any lower bound
Admin uses updatePenalties to set THREE_MONTH_PENALTY, SIX_MONTH_PENALTY, TWELVE_MONTH_PENALTY to 0
Now rage quit always fail since denominator becomes 0 at InfinityStaker.sol#L195 while calculating totalToUser in getRageQuitAmounts
This forces users to remain staked and would not be able to leave the contract
Same can also be done if owner sets insane high penalty forcing user to stay in system
Add below check
require(threeMonthPenalty<=ThreeMonthPenaltyMAX && sixMonthPenalty<=SixMonthPenaltyMAX && twelveMonthPenalty<=TwelveMonthPenaltyMAX); require(threeMonthPenalty!=0 && sixMonthPenalty!=0 && twelveMonthPenalty!=0);
#0 - nneverlander
2022-06-22T13:20:01Z
Duplicate
#1 - HardlyDifficult
2022-07-10T22:16:03Z
Lowering risk since this is an admin function and they could update again if the value was set in error. Converting into a QA report for the warden.
#2 - HardlyDifficult
2022-07-10T22:38:47Z