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: 24/59
Findings: 2
Award: $2,341.16
π 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
1904.8298 USDC - $1,904.83
Checking addresses against zero-address during initialization or during setting is a security best-practice. However, such checks are missing in the createConduit() function in ConduitController.sol
/2022-05-opensea-seaport/contracts/conduit/ConduitController.sol 94: _conduits[conduit].owner = initialOwner;
This is not consistant with the transferOwnership() function where it does check for address(0)
/2022-05-opensea-seaport/contracts/conduit/ConduitController.sol 196: // Ensure the new potential owner is not an invalid address. 197: if (newPotentialOwner == address(0)) { 198: revert NewPotentialOwnerIsZeroAddress(conduit); 199: }
Impact: Allowing zero-addresses may lead to contract redeployments since createConduit() can only be called once.
Avoid floating pragmas for non-library contracts.
While floating pragmas make sense for libraries to allow them to be included with multiple different versions of applications, it may be a security risk for application implementations.
A known vulnerable compiler version may accidentally be selected or security tools might fall-back to an older compiler version ending up checking a different EVM compilation that is ultimately deployed on the blockchain.
It is recommended to pin to a concrete compiler version.
/2022-05-opensea-seaport/contracts/conduit/Conduit.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/conduit/ConduitController.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/AbridgedTokenInterfaces.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/AmountDerivationErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ConduitControllerInterface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ConduitInterface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ConsiderationEventsAndErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ConsiderationInterface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/CriteriaResolutionErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/EIP1271Interface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/FulfillmentApplicationErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ImmutableCreate2FactoryInterface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ReentrancyErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/SeaportInterface.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/SignatureVerificationErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/TokenTransferrerErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ZoneInteractionErrors.sol 2: pragma solidity >=0.8.7; /2022-05-opensea-seaport/contracts/interfaces/ZoneInterface.sol 2: pragma solidity >=0.8.7;
#0 - GalloDaSballo
2022-07-17T18:23:48Z
Valid Low per #56
#1 - GalloDaSballo
2022-07-19T22:15:39Z
1 NC as well
1L 1NC
π 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
436.3303 USDC - $436.33
Removing unused named returns variables can reduce gas usage (MSTOREs/MLOADs) and improve code clarity. To save gas and improve code quality: consider using only one of those.
/2022-05-opensea-seaport/contracts/lib/FulfillmentApplier.sol 48: function _applyFulfillment( 49: AdvancedOrder[] memory advancedOrders, 50: FulfillmentComponent[] calldata offerComponents, 51: FulfillmentComponent[] calldata considerationComponents 52: ) internal view returns (Execution memory execution) { ... 120: return execution; // Execution(considerationItem, offerer, conduitKey);
/2022-05-opensea-seaport/contracts/lib/OrderCombiner.sol 107: function _fulfillAvailableAdvancedOrders( 108: AdvancedOrder[] memory advancedOrders, 109: CriteriaResolver[] memory criteriaResolvers, 110: FulfillmentComponent[][] calldata offerFulfillments, 111: FulfillmentComponent[][] calldata considerationFulfillments, 112: bytes32 fulfillerConduitKey, 113: uint256 maximumFulfilled 114: ) 115: internal 116: returns (bool[] memory availableOrders, Execution[] memory executions) 117: { ... 135: return (availableOrders, executions);
/2022-05-opensea-seaport/contracts/lib/OrderFulfiller.sol 457: function _convertOrdersToAdvanced(Order[] calldata orders) 458: internal 459: pure 460: returns (AdvancedOrder[] memory advancedOrders) ... 478: return advancedOrders;
/2022-05-opensea-seaport/contracts/lib/OrderValidator.sol 104: function _validateOrderAndUpdateStatus( 105: AdvancedOrder memory advancedOrder, 106: CriteriaResolver[] memory criteriaResolvers, 107: bool revertOnInvalid, 108: bytes32[] memory priorOrderHashes 109: ) 110: internal 111: returns ( 112: bytes32 orderHash, 113: uint256 newNumerator, 114: uint256 newDenominator 115: ) 116: { ... /2022-05-opensea-seaport/contracts/lib/OrderValidator.sol 242: return (orderHash, numerator, denominator);
/2022-05-opensea-seaport/contracts/lib/Verifiers.sol 37: function _verifyTime( 38: uint256 startTime, 39: uint256 endTime, 40: bool revertOnInvalid 41: ) internal view returns (bool valid) { ... 50: return false;
/2022-05-opensea-seaport/contracts/lib/Verifiers.sol 102: function _verifyOrderStatus( 103: bytes32 orderHash, 104: OrderStatus memory orderStatus, 105: bool onlyAllowUnused, 106: bool revertOnInvalid 107: ) internal pure returns (bool valid) { ... 116: return false; 133: return false;
Due to how constant variables are implemented (replacements at compile-time), an expression assigned to a constant variable is recomputed each time that the variable is used, which wastes some gas.
recommend hard coding constants to save gas
/2022-05-opensea-seaport/contracts/lib/ConsiderationConstants.sol 235: uint256 constant BasicOrder_offerItem_typeHash_ptr = DefaultFreeMemoryPointer;
/2022-05-opensea-seaport/contracts/lib/TokenTransferrerConstants.sol 81: bytes4 constant ERC1155_safeBatchTransferFrom_selector = bytes4( 82: bytes32(ERC1155_safeBatchTransferFrom_signature) 83: ); 85: uint256 constant ERC721_transferFrom_signature = ERC20_transferFrom_signature;
for variables only used once, changing it to inline saves gas
/2022-05-opensea-seaport/contracts/conduit/ConduitController.sol 425: uint256 totalChannels = _conduits[conduit].channels.length;
/2022-05-opensea-seaport/contracts/lib/AmountDeriver.sol 56: uint256 totalBeforeDivision = ( 114: uint256 valueTimesNumerator = value * numerator;
Uninitialized variables are assigned with the types default value.
Explicitly initializing a variable with it's default value costs unnecesary gas.
/2022-05-opensea-seaport/contracts/conduit/Conduit.sol 66: for (uint256 i = 0; i < totalStandardTransfers; ) { //@audit dont initialize i 130: for (uint256 i = 0; i < totalStandardTransfers; ) {
/2022-05-opensea-seaport/contracts/lib/AmountDeriver.sol 44: uint256 extraCeiling = 0;
/2022-05-opensea-seaport/contracts/lib/BasicOrderFulfiller.sol 948: for (uint256 i = 0; i < totalAdditionalRecipients; ) { 1040: for (uint256 i = 0; i < totalAdditionalRecipients; ) {
/2022-05-opensea-seaport/contracts/lib/CriteriaResolution.sol 56: for (uint256 i = 0; i < totalCriteriaResolvers; ++i) { 166: for (uint256 i = 0; i < totalAdvancedOrders; ++i) { 184: for (uint256 j = 0; j < totalItems; ++j) { //@audit dont initialize j 199: for (uint256 j = 0; j < totalItems; ++j) {
/2022-05-opensea-seaport/contracts/lib/OrderCombiner.sol 181: for (uint256 i = 0; i < totalOrders; ++i) { 247: for (uint256 j = 0; j < offer.length; ++j) { 291: for (uint256 j = 0; j < consideration.length; ++j) { 373: for (uint256 i = 0; i < totalOrders; ++i) {
/2022-05-opensea-seaport/contracts/lib/OrderFulfiller.sol 217: for (uint256 i = 0; i < orderParameters.offer.length; ) { 306: for (uint256 i = 0; i < orderParameters.consideration.length; ) {
/2022-05-opensea-seaport/contracts/lib/OrderValidator.sol 272: for (uint256 i = 0; i < totalOrders; ) { 350: for (uint256 i = 0; i < totalOrders; ) {
The code can be optimized by minimising the number of SLOADs. SLOADs are expensive (100 gas) compared to MLOADs/MSTOREs (3 gas).
array lengths should be cached outside of the loop
/2022-05-opensea-seaport/contracts/lib/OrderCombiner.sol 247: for (uint256 j = 0; j < offer.length; ++j) { 291: for (uint256 j = 0; j < consideration.length; ++j) {
/2022-05-opensea-seaport/contracts/lib/OrderFulfiller.sol 217: for (uint256 i = 0; i < orderParameters.offer.length; ) { 306: for (uint256 i = 0; i < orderParameters.consideration.length; ) {
Use calldata instead of memory for function parameters saves gas
use calldata instead of memory if the function argument is only read.
/2022-05-opensea-seaport/contracts/lib/Consideration.sol 301: AdvancedOrder[] memory advancedOrders, 399: AdvancedOrder[] memory advancedOrders,
/2022-05-opensea-seaport/contracts/lib/CriteriaResolution.sol 45: CriteriaResolver[] memory criteriaResolvers 244: bytes32[] memory proof
/2022-05-opensea-seaport/contracts/lib/Executor.sol 55: ReceivedItem memory item,
/2022-05-opensea-seaport/contracts/lib/FulfillmentApplier.sol 142: AdvancedOrder[] memory advancedOrders, 144: FulfillmentComponent[] memory fulfillmentComponents,
/2022-05-opensea-seaport/contracts/lib/OrderCombiner.sol 108: AdvancedOrder[] memory advancedOrders, 109: CriteriaResolver[] memory criteriaResolvers, 159: AdvancedOrder[] memory advancedOrders, 160: CriteriaResolver[] memory criteriaResolvers,
/2022-05-opensea-seaport/contracts/lib/OrderFulfiller.sol 76: AdvancedOrder memory advancedOrder, 77: CriteriaResolver[] memory criteriaResolvers,
/2022-05-opensea-seaport/contracts/lib/OrderFulfiller.sol 400: OfferItem[] memory offer, 401: ConsiderationItem[] memory consideration
/2022-05-opensea-seaport/contracts/lib/OrderValidator.sol 105: AdvancedOrder memory advancedOrder, 106: CriteriaResolver[] memory criteriaResolvers, 108: bytes32[] memory priorOrderHashes
/2022-05-opensea-seaport/contracts/lib/ZoneInteraction.sol 105: AdvancedOrder memory advancedOrder, 106: CriteriaResolver[] memory criteriaResolvers, 107: bytes32[] memory priorOrderHashes,