- Total Prize Pool: $60,500 USDC
- HM awards: $42,500 USDC
- QA report awards: $5,000 USDC
- Gas report awards: $2,500 USDC
- Judge + presort awards: $10,000 USDC
- Scout awards: $500 USDC
- Join C4 Discord to register
- Submit findings using the C4 form
- Read our guidelines for more details
- Starts November 8, 2022 20:00 UTC
- Ends November 13, 2022 20:00 UTC
The C4audit output for the contest can be found here.
Note for C4 wardens: Anything included in the C4udit output is considered a publicly known issue and is ineligible for awards.
These are the top-level contracts of the project.
-
LooksRareAggregator: An NFT liquidity aggregator that allows anyone to buy ERC721/ERC1155 tokens from multiple marketplaces in a single transaction. Users can only execute trades through proxies that have been whitelisted by the contract owner.
-
ERC20EnabledLooksRareAggregator: The entrypoint for purchases that are denominated in ERC20 tokens instead of native ETH. It still executes trades through LooksRareAggregator. The purpose of having an extra aggregator is to prevent LooksRareAggregator's ownership from being compromised and malicious proxies can steal users' ERC20 tokens.
-
LooksRareProxy : A proxy to execute trades on LooksRare.
-
SeaportProxy: A proxy to execute trades on Seaport.
Contract | SLOC | Purpose | Libraries used |
---|---|---|---|
IERC20EnabledLooksRareAggregator | 12 | ERC20EnabledLooksRareAggregator interface | N/A |
ILooksRareAggregator | 32 | LooksRareAggregator interface | N/A |
IProxy | 16 | Generic proxy interface | N/A |
SeaportInterface | 70 | Seaport interface | N/A |
ConsiderationEnums | 53 | Seaport consideration enums | N/A |
ConsiderationStructs | 122 | Seaport consideration structs | N/A |
OrderEnums | 2 | Aggregator order enums | N/A |
OrderStructs | 22 | Aggregator order structs | N/A |
LooksRareProxy | 101 | Execute trades on LooksRare protocol (calls LooksRare) | @looksrare/contracts-exchange-v1 |
SeaportProxy | 206 | Execute trades on Seaport (calls Seaport) | N/A |
ERC20EnabledLooksRareAggregator | 35 | Aggregate ERC20 trades to different marketplaces | N/A |
LooksRareAggregator | 169 | Aggregate trades to different marketplaces | N/A |
TokenReceiver | 29 | Contains callbacks that enable contracts to receive ERC721/ERC1155 tokens | N/A |
TokenTransferrer | 19 | Enable contracts to make outward ERC721/ERC1155 token transfers | N/A |
TokenRescuer | 18 | Enable owners to rescue trapped tokens from contracts | N/A |
ReentrancyGuard | 14 | Prevent re-entrancy attacks | N/A |
OwnableTwoSteps | 59 | Contract ownership logic, specifically 2 steps ownership transfers | N/A |
SignatureChecker | 50 | Enable contracts to validate EIP-712 signatures | N/A |
LowLevelERC20Approve | 16 | Enable contracts to make ERC20 approvals | N/A |
LowLevelERC20Transfer | 31 | Enable contracts to make ERC20 transfers | N/A |
LowLevelERC721Transfer | 14 | Enable contracts to make ERC721 transfers | N/A |
LowLevelERC1155Transfer | 30 | Enable contracts to make ERC1155 transfers | N/A |
LowLevelETH | 33 | Enable contracts to make ETH transfers | N/A |
IERC20 | 15 | ERC20 interface | N/A |
IERC721 | 28 | ERC721 interface | N/A |
IERC1155 | 34 | ERC1155 interface | N/A |
The main area of focus is on the 2 aggregators and the 2 proxies,
- whether it is possible for a buyer to execute a malicious function call
- whether it is possible for any tokens (ETH / ERC20 / ER721 / ERC1155) to be trapped inside the contracts
- whether it is possible for any assets to be stolen
Fees logic is only implemented in SeaportProxy because the LooksRare protocol already charges a fee.
Contract owners can set the fee basis point and recipient for each proxy. Before executing a trade, the client should fetch each proxy's
fee data and include the returned basis points in the trade data's maxFeeBp
parameter to prevent the fee basis points from suddenly icnreasing
beyond the buyer's acceptable fee levels.
If a trade contains multiple orders and they are denominated in different currencies, they should be sorted by currency in the client to reduce the number of ETH/ERC20 transfers.
Buyers can decide whether they want their transactions to be all-or-nothing or accepting partial executions with the bool flag isAtomic
.
Proxies can only be called in the context of LooksRareAggregator
through delegatecall
.
The line if (address(this) != aggregator) revert InvalidCaller();
does it.
- If you have a public code repo, please share it here: N/A
- How many contracts are in scope?: 26
- Total SLoC for these contracts?: 1230
- How many external imports are there?: 11
- How many separate interfaces and struct definitions are there for the contracts within scope?: 7
- Does most of your code generally use composition or inheritance?: Yes
- How many external calls?: 3
- What is the overall line coverage percentage provided by your tests?: Should be 90%+
- Is there a need to understand a separate part of the codebase / get context in order to audit this part of the protocol?: True.
- Please describe required context: The project integrates with Seaport and LooksRare's exchange protocol.
- Does it use an oracle?: False
- Does the token conform to the ERC20 standard?: We aren't creating a new token.
- Are there any novel or unique curve logic or mathematical models?: No
- Does it use a timelock function?: Yes but only for contract ownership management and not business critical functions.
- Is it an NFT?: No
- Does it have an AMM?: No
- Is it a fork of a popular project?: False
- Does it use rollups?: False
- Is it multi-chain?: False
- Does it use a side-chain?: False
rm -Rf 2022-11-looksrare || true && git clone https://github.com/code-423n4/2022-11-looksrare.git && cd 2022-11-looksrare && yarn install && cp .env.template .env && FORGE_GAS_REPORT=true FOUNDRY_PROFILE=local forge test
yarn install
To reduce wait time, run any build/test related commands with FOUNDRY_PROFILE=local. It turns off the Yul IR pipeline.
cp .env.template .env
FOUNDRY_PROFILE=local forge build
cp .env.template .env
forge test # via_ir: true
FOUNDRY_PROFILE=local forge test # via_ir: false
FOUNDRY_PROFILE=local forge test --match-contract GemSwapBenchmarkTest
FOUNDRY_PROFILE=local forge test --match-contract LooksRareProxyBenchmarkTest
FOUNDRY_PROFILE=local forge test --match-contract SeaportProxyBenchmarkTest
pip3 install slither-analyzer
pip3 install solc-select
solc-select install 0.8.17
solc-select use 0.8.17
slither --solc solc-0.8.17 .
-
There are a number of ignored detectors in
slither.config.json
. We have reviewed every warning and deemed those to be safe to ignore. -
You will run into the error
Missing function Incorrect ternary conversion marketplace.fulfillAdvancedOrder{value: if currency == address(0) then price else 0}(advancedOrder,new CriteriaResolver[](0),bytes32(0),recipient) contracts/proxies/SeaportProxy.sol#199-218
when you first runslither
, the solution is to movecurrency == address(0) ? price : 0
to its own variable. Although we havevia_ir
turned on for production environment, we have decided to keep it turned off locally as it takes a long time to build. Therefore we are not able to make this ternary operator its own variable without running into theStack Too Deep
error.
forge coverage --report lcov
LCOV_EXCLUDE=("test/*" "contracts/prototype/*")
echo $LCOV_EXCLUDE | xargs lcov --output-file lcov-filtered.info --remove lcov.info
genhtml lcov-filtered.info --output-directory out
open out/index.html