OpenSea Seaport contest - sirhashalot's results

A marketplace contract for safely and efficiently creating and fulfilling orders for ERC721 and ERC1155 items.

General Information

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

OpenSea

Findings Distribution

Researcher Performance

Rank: 40/59

Findings: 1

Award: $474.36

🌟 Selected for report: 0

🚀 Solo Findings: 0

1. Unnecessary explicit initialization of variables with default values

If a variable is not set/initialized, it has the default value (0 for uint, false for bool, etc.). Explicitly initializing a variable with its default value is an anti-pattern and wastes gas.

The OrderCombiner.sol contract has more than ten explicit initializations of default values. Other contract have more examples. Examples include:

To fix this, remove explicit initializations for default values.

2. Use unchecked for increment

Consider the following generic for loop:

for (uint i = 0; i < length; i++) {
    // do something that doesn't change the value of i
}

In this example, the for loop post condition, i.e., i++ involves checked arithmetic, which is not required. This is because the value of i is always strictly less than length <= 2**256 - 1. Therefore, the theoretical maximum value of i to enter the for-loop body is 2**256 - 2. This means that the i++ in the for loop can never overflow. Regardless, the overflow checks are performed by the compiler.

Unfortunately, the Solidity optimizer is not smart enough to detect this and remove the checks. One can manually do this by:

for (uint i = 0; i < length; i = unchecked_inc(i)) {
    // do something that doesn't change the value of i
}

function unchecked_inc(uint i) returns (uint) {
    unchecked {
        return i + 1;
    }
}

Above code and explanation from hrkrshnn.

The OrdrCombiner.sol contract has more than 5 loops that can be improved this way. Examples include:

To fix, use unchecked increment in loops.

3. iszero assembly should replace == 0

The iszero opcode is useful when comparing variables to zero. t11s suggested overusing this improvement on twitter.

The Assertions.sol and OrderCombiner.sol contracts have more than 5 zero comparisons that can be improved this way. Examples include:

To fix, replace == 0 with iszero.

4. Use vyper instead of solidity

Vyper contracts normally use less gas than their solidity counterparts. The possible savings was demonstrated for Seaport by doggo and a more general example was shown here. Seaport is written in solidity and yul, not vyper. Switching some or all of the contracts to vyper can result in gas savings.

To fix, replace solidity contracts with vyper code.

#0 - HardlyDifficult

2022-06-26T16:25:36Z

Unnecessary explicit initialization of variables with default values

In my testing these changes seem to make very little difference.

Use unchecked for increment

This will provide small savings.

iszero assembly should replace == 0

I like how you reference t11s own tweet here :) This could be a worthwhile change to consider including here.

Use vyper instead of solidity

Potentially. I saw 0age mention a working group exploring this more. Very curious to see if that concludes, would love a full featured comparison of Seaport in Solidity/Yul vs Vyper

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter