Platform: Code4rena
Start Date: 08/11/2022
End Date: 13/11/2022
Period: 5 days
Status: Completed
Pot Size: $60,500 USDC
Participants: 72
Reporter: itsmetechjay
Judge: Picodes
Id: 178
League: ETH
cccz | 1/72 | $10,871.41 | 2 | 0 | 0 | 1 | 1 | Grade B | 0 | 0 |
KingNFT | 2/72 | $10,871.41 | 2 | 0 | 0 | 1 | 1 | Grade B | 0 | 0 |
0xSmartContract | 3/72 | $5,205.96 | 2 | 0 | 0 | 1 | 0 | Grade A | 0 | 0 |
ronnyx2017 | 4/72 | $4,875.78 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
0x52 | 5/72 | $3,938.27 | 3 | 0 | 0 | 2 | 0 | Grade B | 0 | 0 |
carrotsmuggler | 6/72 | $3,864.16 | 3 | 0 | 0 | 2 | 0 | Grade B | 0 | 0 |
IllIllI | 7/72 | $1,286.35 | 2 | 0 | 0 | 0 | 0 | Grade A | Grade A | 0 |
CloudX | 8/72 | $735.51 | 1 | 0 | 0 | 0 | 0 | 0 | - | 0 |
RaymondFam | 9/72 | $429.24 | 1 | 0 | 0 | 0 | 0 | Grade A | 0 | 0 |
0x1f8b | 10/72 | $411.01 | 2 | 0 | 0 | 0 | 0 | Grade A | Grade B | 0 |
Auditor per page
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,
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
git clone
to running all tests in one line)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 run slither
, the solution is to move currency == address(0) ? price : 0
to its own variable. Although we have via_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 the Stack 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