Platform: Code4rena
Start Date: 29/06/2022
Pot Size: $50,000 USDC
Total HM: 20
Participants: 133
Period: 5 days
Judge: hickuphh3
Total Solo HM: 1
Id: 142
League: ETH
Rank: 106/133
Findings: 1
Award: $21.24
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: GalloDaSballo
Also found by: 0v3rf10w, 0x1f8b, 0xA5DF, 0xDjango, 0xHarry, 0xKitsune, 0xNazgul, 0xNineDec, 0xc0ffEE, 0xf15ers, 0xkatana, 0xsanson, ACai, Aymen0909, Bnke0x0, BowTiedWardens, Chom, ElKu, Fitraldys, Funen, Haruxe, Hawkeye, IllIllI, JC, JohnSmith, Kaiziron, Kenshin, Lambda, Limbooo, MadWookie, Metatron, MiloTruck, Picodes, PwnedNoMore, Randyyy, RedOneN, ReyAdmirado, Ruhum, Sm4rty, StErMi, StyxRave, TerrierLover, TomJ, Tomio, UnusualTurtle, Waze, Yiko, _Adam, __141345__, ajtra, ak1, apostle0x01, asutorufos, c3phas, cRat1st0s, catchup, codetilda, cryptphi, datapunk, defsec, delfin454000, durianSausage, exd0tpy, fatherOfBlocks, gogo, grrwahrr, hake, hansfriese, horsefacts, ignacio, jayfromthe13th, joestakey, ladboy233, m_Rassska, mektigboy, minhquanym, mrpathfindr, natzuu, oyc_109, rajatbeladiya, reassor, rfa, robee, rokinot, sach1r0, saian, sashik_eth, simon135, slywaters, swit, z3s, zeesaw, zer0dot
21.2394 USDC - $21.24
order.expiration
position expiration value is calculated by adding block.timestamp and duration, order's expiration value is not used
positionExpirations[order.isLong ? uint256(orderHash) : positionId] = block.timestamp + order.duration;
constant variable can be changed from public to internal visibility to avoid getter function
bytes32 public constant ERC721ASSET_TYPE_HASH = keccak256(abi.encodePacked("ERC721Asset(address token,uint256 tokenId)"));
bytes32 public constant ERC20ASSET_TYPE_HASH = keccak256(abi.encodePacked("ERC20Asset(address token,uint256 tokenAmount)"));
bytes32 public constant ORDER_TYPE_HASH
require statements can be reordered to save gas on revert
isLong condition can be placed on the top
bytes32 orderHash = hashOrder(order); // check user owns the position require(ownerOf(uint256(orderHash)) == msg.sender, "Not owner"); // check position is long require(order.isLong, "Can only exercise long positions");
Conditions in require statement can be re-ordered so that if position is exercised it consumes less gas
require(block.timestamp > positionExpirations[longPositionId] || isExercised, "Must be exercised or expired");
can be changed to
require(isExercised || block.timestamp > positionExpirations[longPositionId], "Must be exercised or expired");
variables initialization with default values(0) can be avoided as it already contains default values, order length can be cached in a variables and re-used instead of querying length in every iteration, post-increment can be replaced with pre-increment ++i and unchecked can be added to save gas
L556: for (uint256 i = 0; i < orders.length; i++) { L594: for (uint256 i = 0; i < assets.length; i++) { L611: for (uint256 i = 0; i < assets.length; i++) { L627: for (uint256 i = 0; i < floorTokens.length; i++) { L637: for (uint256 i = 0; i < assets.length; i++) { L647: for (uint256 i = 0; i < floorTokens.length; i++) { L658: for (uint256 i = 0; i < floorTokens.length; i++) { L670: for (uint256 i = 0; i < whitelist.length; i++) { L728: for (uint256 i = 0; i < arr.length; i++) { L742: for (uint256 i = 0; i < arr.length; i++) {
Public functions that are not called inside the contract can be converted to external
function domainSeparatorV4() public view returns (bytes32) { return _domainSeparatorV4(); }
function tokenURI(uint256 id) public view override returns (string memory) {