code-423n4 / 2022-05-opensea-seaport-findings

1 stars 0 forks source link

Gas Optimizations #191

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Gas report

Unnecessary packing of strings

In ConsiderationBase.sol there are strings that are redundantly being packed. Consider passing them as a single string.

Assembly block optimization

In GettersAndDerivers.sol there is such assembly fragment of a block:

            // Set the pointer to the first offer's head.
            offerArrPtr := add(offerArrPtr, OneWord)

            // Iterate over the offer items.
            // prettier-ignore
            for { let i := 0 } lt(i, offerLength) {
                i := add(i, 1)
            } {
                // Read the pointer to the offer data and subtract one word
                // to get typeHash pointer.
                let ptr := sub(mload(offerArrPtr), OneWord)

                // Read the current value before the offer data.
                let value := mload(ptr)

                // Write the type hash to the previous word.
                mstore(ptr, typeHash)

                // Take the EIP712 hash and store it in the hash array.
                mstore(hashArrPtr, keccak256(ptr, EIP712_OfferItem_size))

                // Restore the previous word.
                mstore(ptr, value)

                // Increment the array pointers by one word.
                offerArrPtr := add(offerArrPtr, OneWord)
                hashArrPtr := add(hashArrPtr, OneWord)
            }

Note that offerArrPtr is incremented before the loop and at the end of it. It is not used after the loop has finished its execution. Thus, the incrementation can be put as the first operation in the loop and deleted from before the loop. This will save deployment gas, decrease code size and save execution gas.

Also, here such code can be found:

            // Derive the offer hash using the hashes of each item.
            offerHash := keccak256(
                mload(FreeMemoryPointerSlot),
                mul(offerLength, OneWord)
            )

There are two possible optimization that can be used here. One, the first mload operation can be skipped by duplicating teh earlier read value from stack (before modifications) (here),

The second possible optimization is to use bitwise shift instead of multiplication by a power of 2 - it's more gas efficient.

HardlyDifficult commented 2 years ago

Unnecessary packing of strings

This only impacts the constructor. Since this does not impact end-users, it may be worth keeping the code as-is for readability.

Assembly block optimization

These changes may offer a small savings and be worth considering.