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: 41/59
Findings: 1
Award: $454.28
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
454.2791 USDC - $454.28
If any code exists in the calculated conduit address, the CREATE2 will throws immediately. Ref: https://github.com/ethereum/EIPs/issues/684
// If derived conduit exists, as evidenced by comparing runtime code... if (conduit.codehash == _CONDUIT_RUNTIME_CODE_HASH) { // Revert with an error indicating that the conduit already exists. revert ConduitAlreadyExists(conduit); } // Deploy the conduit via CREATE2 using the conduit key as the salt. new Conduit{ salt: conduitKey }();
if (isOpen && !channelPreviouslyOpen) { // A } else if (!isOpen && channelPreviouslyOpen) { // B }
change to
if (channelPreviouslyOpen) { if (!isOpen){ // B } } else { if (isOpen){ // A } }
function _nameString() internal pure override returns (string memory) { // Return the name of the contract. return "Seaport"; }
to
function _nameString() internal pure override returns (string memory) { // Return the name of the contract. return _name(); }
Use uint256 or enum instead of bool will save gas https://github.com/code-423n4/2022-05-opensea-seaport/blob/4140473b1f85d0df602548ad260b1739ddd734a5/contracts/conduit/Conduit.sol#L33-L34
mapping(address => bool) private _channels;
to
mapping(address => uint256) private _channels;
with the respective changes to represent isOpen as 1 and !isOpen as 0
Instead of using a bool[], multiple bool can be packed into the same memory slot in a bytes32. This would limit the maximum number of order to 255, but shouldn't be a problem practically.
contracts/lib/Consideration.sol:225: returns (bool[] memory availableOrders, Execution[] memory executions) contracts/lib/Consideration.sol:311: returns (bool[] memory availableOrders, Execution[] memory executions) contracts/lib/OrderCombiner.sol:116: returns (bool[] memory availableOrders, Execution[] memory executions) contracts/lib/OrderCombiner.sol:452: returns (bool[] memory availableOrders, Execution[] memory executions) contracts/lib/OrderCombiner.sol:567: ) internal returns (bool[] memory availableOrders) { contracts/lib/OrderCombiner.sol:572: availableOrders = new bool[](totalOrders); contracts/interfaces/ConsiderationInterface.sol:172: returns (bool[] memory availableOrders, Execution[] memory executions); contracts/interfaces/ConsiderationInterface.sol:245: returns (bool[] memory availableOrders, Execution[] memory executions); contracts/interfaces/SeaportInterface.sol:171: returns (bool[] memory availableOrders, Execution[] memory executions); contracts/interfaces/SeaportInterface.sol:244: returns (bool[] memory availableOrders, Execution[] memory executions);
#0 - HardlyDifficult
2022-06-26T16:17:06Z
Unnecessary codehash compare
This may be a worthwhile optimization to make.
Optimize control flow in updateChannel to cut a MLOAD
Updating channels is not a common operation and it doesn't impact end-users. This may offer small savings but not for a critical path.
Use _name() in _nameString()
It's not clear this would save gas for real transactions.
Use uint256 instead of bool in _channels mapping
This may offer very small savings.
Pack multiple bool into a bytes32
This could provide some savings, although integrations are less straightforward so it may not be worth including.