Platform: Code4rena
Start Date: 20/05/2022
Pot Size: $1,000,000 USDC
Total HM: 4
Participants: 59
Period: 14 days
Judge: leastwood
Id: 128
League: ETH
Rank: 22/59
Findings: 2
Award: $2,412.41
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Spearbit
Also found by: 0xsanson, Chom, IllIllI, OriDabush, Saw-mon_and_Natalie, broccoli, cccz, cmichel, csanuragjain, foobar, hack3r-0m, hickuphh3, hubble, hyh, ilan, kebabsec, mayo, oyc_109, peritoflores, rfa, scaraven, sces60107, shung, sorrynotsorry, tintin, twojoy, zkhorse, zzzitron
1946.4026 USDC - $1,946.40
Issue: Interface mentions that the last twenty bytes of the supplied conduit key must match the caller whereas implementation contract mentions that the first twenty bytes of the supplied conduit key must match the caller
Recommendation: Change ConduitControllerInterface.sol#L105 to mention first twenty bytes of the supplied conduit key must match the caller
Issue: if deployment fails conduit will be address 0 and since codehash will not match, contract will assume that conduit has been created and will update _conduits[0x00]
Recommendation: Add below check to createConduit
address conduitAddr=new Conduit{ salt: conduitKey }(); require(conduitAddr!=address(0), "Conduit creation failed");
Issue: While fulfilling orders there is no check to verify zero address check for offerer/zone (In case order type is open zero address for both would be accepted)
Recommendation: Add below check to _applyFractionsAndTransferEach
require(offerer!=address(0) && zone!=address(0),"Incorrect offerer or zone");
Issue: Create2 exposes a computeAddress function which can be used to calculate the address of Conduit but Conduit instead uses a homebrew calculation in getConduit.
Recommendation: Make use of Create2.computeAddress function to determine conduit address in getConduit function
#0 - HardlyDifficult
2022-06-19T18:49:53Z
#1 - HardlyDifficult
2022-06-26T18:04:53Z
Incorrect documentation can cause confusion
It would be nice to fix the comments here.
Not verifying if create2 deployment failed
new
should revert if the creation fails.
offerer/zone should not be address(0)
I'm not sure the recommendation here is valid. Zone is not required, and a missing offerer would later revert (e.g. on the 721 transfer call downstream).
Conduit address can be computed using predefined function
This is recommending using an OZ dependency here. They don't currently use any OZ libraries and the implementation referenced appears to be valid.
Conduit can be rendered useless
See comment in #56
🌟 Selected for report: Dravee
Also found by: 0x1f8b, 0x29A, 0xalpharush, Chom, Czar102, Hawkeye, IllIllI, MaratCerby, MiloTruck, NoamYakov, OriDabush, RoiEvenHaim, Spearbit, Tadashi, TerrierLover, TomJ, asutorufos, cccz, cmichel, csanuragjain, defsec, delfin454000, djxploit, ellahi, foobar, gzeon, hake, hickuphh3, ignacio, ilan, joestakey, kaden, mayo, ming, oyc_109, peritoflores, rfa, sach1r0, sashik_eth, shung, sirhashalot, twojoy, zer0dot, zkhorse
466.0106 USDC - $466.01
Contract: https://github.com/code-423n4/2022-05-opensea-seaport/blob/main/contracts/lib/OrderFulfiller.sol#L75 https://github.com/code-423n4/2022-05-opensea-seaport/blob/main/reference/lib/ReferenceOrderFulfiller.sol#L80
Issue: If Offer & Consideration length is zero then Order fulfillment does not need to do anything and should return immediately to prevent Gas
Recommendation: Have below check added in _validateAndFulfillAdvancedOrder function
require(orderParameters.offer.length>0 && orderParameters.consideration.length>0 , "Incorrect paramters");
Issue: If order is not fulfilled then there is no need to run criteria resolver
Recommendation: Add below check in _applyCriteriaResolversAdvanced
if (advancedOrder.numerator == 0) { return; }
Issue: conduit.codehash == _CONDUIT_RUNTIME_CODE_HASH is currently used to know if conduit is already existing or not. The same could be done in gas saving way using bytes32(0) check
Recommendation: Replace check with below in createConduit:
if(!_conduits[conduit].key == bytes32(0)){ revert ConduitAlreadyExists(conduit); }
Contract: https://github.com/code-423n4/2022-05-opensea-seaport/blob/main/contracts/lib/Executor.sol#L260
Issue: If conduitKey == bytes32(0) then there is no need to check _triggerIfArmedAndNotAccumulatable since there will not be any new transfer insert.
Recommendation: The recommendation should be applied for all transfers. Change the function implementation like below:
function _transferERC20( address token, address from, address to, uint256 amount, bytes32 conduitKey, bytes memory accumulator ) internal { _assertNonZeroAmount(amount); if (conduitKey == bytes32(0)) { _performERC20Transfer(token, from, to, amount); } else { // Add trigger here _triggerIfArmedAndNotAccumulatable(accumulator, conduitKey); _insert( conduitKey, accumulator, uint256(1), token, from, to, uint256(0), amount ); } }
Contract: https://github.com/code-423n4/2022-05-opensea-seaport/blob/main/contracts/conduit/Conduit.sol#L174
Issue: If amount is not correct then there is no need for transfer to proceed
Recommendation: Add below check in _transfer function:
require(item.amount!=0, "Invalid amount")
Contract: https://github.com/code-423n4/2022-05-opensea-seaport/blob/main/contracts/conduit/Conduit.sol#L163
Issue: Add a check to see if channel updating is actually not required as this will return ConduitController.sol#L118 before it does unrequired updation and will save gas
Recommendation: Add below check if updating is not required:
require(_channels[channel]!=isOpen, "Already in same state");
#0 - HardlyDifficult
2022-06-26T16:06:53Z
Offer & Consideration length should be greater than 0 while fulfilling orders
Assuming this is valid, it would add a small cost to the happy case scenario which is likely more important to optimize for. It's not clear that this change should be included.
Criteria resolver should be skipped if order is not fulfilled
This could offer a small savings but the happy case paths should be tested to ensure this is not adding cost to most orders in order to benefit what may be a corner case.
Existing Conduit check can be done with lesser gas Insert is not required when Conduit is not used
It does seem changes such as this could offer savings.
Transfer not required if amount is 0
This could be worth including if 0 is not already checked elsewhere, however adding this check would add a small cost to the happy case path so it may be best to avoid.
No need to update channel if same state
This could provide some savings, but changing channels is not a common operation and end-users are not impacted.