Platform: Code4rena
Start Date: 06/09/2022
Pot Size: $90,000 USDC
Total HM: 33
Participants: 168
Period: 9 days
Judge: GalloDaSballo
Total Solo HM: 10
Id: 157
League: ETH
Rank: 98/168
Findings: 2
Award: $106.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Lambda
Also found by: 0x1337, 0x1f8b, 0x4non, 0x85102, 0xA5DF, 0xNazgul, 0xSmartContract, 0xbepresent, 0xc0ffEE, 8olidity, Aymen0909, B2, Bnke0x0, CRYP70, Captainkay, CertoraInc, Ch_301, Chom, ChristianKuri, CodingNameKiki, Deivitto, Diana, DimitarDimitrov, ElKu, EthLedger, Franfran, Funen, GimelSec, JansenC, Jeiwan, Jujic, Lead_Belly, MEP, MasterCookie, MiloTruck, Noah3o6, PPrieditis, PaludoX0, Picodes, PwnPatrol, R2, Randyyy, RaymondFam, Respx, ReyAdmirado, Rolezn, Samatak, Tointer, Tomo, V_B, Waze, _Adam, __141345__, a12jmx, ak1, asutorufos, azephiar, ballx, bharg4v, bin2chen, bobirichman, brgltd, bulej93, c3phas, cccz, ch0bu, cloudjunky, cryptonue, cryptostellar5, cryptphi, csanuragjain, d3e4, datapunk, davidbrai, delfin454000, dharma09, dic0de, dipp, djxploit, eierina, erictee, fatherOfBlocks, gogo, hansfriese, hyh, imare, indijanc, izhuer, jonatascm, ladboy233, leosathya, lucacez, lukris02, m9800, martin, minhtrng, ne0n, neumo, oyc_109, p_crypt0, pashov, pauliax, pcarranzav, pedr02b2, peritoflores, pfapostol, rbserver, ret2basic, robee, rvierdiiev, sach1r0, sahar, scaraven, sikorico, simon135, slowmoses, sorrynotsorry, tnevler, tonisives, volky, yixxas, zkhorse, zzzitron
60.7742 USDC - $60.77
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L363
It is a good idea to add a require()
statement that checks the return value of ERC20 token transfers or to use something like OpenZeppelin’s safeTransfer()
/safeTransferFrom()
unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures of transfers and affect token accounting in contract.
However, using require() to check transfer return values could lead to issues with non-compliant ERC20 tokens which do not return a boolean value. Therefore, it’s highly advised to use OpenZeppelin’ssafeTransfer()
/safeTransferFrom()
.
L363: IWETH(WETH).transfer(_to, _amount);
Consider using safeTransfer()
/safeTransferFrom()
instead of transfer()/transferFrom().
#0 - GalloDaSballo
2022-09-17T01:23:39Z
WETH is known to never revert
#1 - GalloDaSballo
2022-09-20T19:07:27Z
🌟 Selected for report: pfapostol
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xA5DF, 0xSmartContract, 0xc0ffEE, 0xkatana, Aymen0909, Bnke0x0, CertoraInc, Chandr, CodingNameKiki, Cr4ckM3, Deivitto, DimSon, Franfran, JAGADESH, JC, Jeiwan, Lambda, LeoS, Matin, Metatron, Migue, MiloTruck, PPrieditis, PaludoX0, R2, RaymondFam, Respx, ReyAdmirado, Rolezn, Saintcode_, Samatak, SnowMan, StevenL, Tointer, TomJ, Tomo, WatchDogs, Waze, _Adam, __141345__, ajtra, asutorufos, ballx, brgltd, bulej93, c3phas, ch0bu, dharma09, djxploit, durianSausage, easy_peasy, fatherOfBlocks, gianganhnguyen, gogo, imare, leosathya, lucacez, martin, oyc_109, pauliax, peiw, prasantgupta52, ret2basic, rfa, robee, sikorico, simon135, tofunmi, volky, wagmi, zishansami
45.4138 USDC - $45.41
If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
Instances include:
MetadataRenderer.sol#L133 MetadataRenderer.sol#L189 MetadataRenderer.sol#L229
Treasury.sol#L162
the equivalent of (a && b)
is !(!a || !b)
Even with the 10k Optimizer enabled, OR
conditions cost less than their equivalent AND
conditions.
Compare in Remix this example contract’s 2 diffs (or any test contract of your choice, as experimentation always shows the same results).
pragma solidity 0.8.13; contract Test { bool isOpen; bool channelPreviouslyOpen; function boolTest() external view returns (uint) { - if (isOpen && !channelPreviouslyOpen) { + if (!(!isOpen || channelPreviouslyOpen)) { return 1; - } else if (!isOpen && channelPreviouslyOpen) { + } else if (!(isOpen || !channelPreviouslyOpen)) { return 2; } } function setBools(bool _isOpen, bool _channelPreviouslyOpen) external { isOpen = _isOpen; channelPreviouslyOpen= _channelPreviouslyOpen; } }
effectively saving 12 gas.
It’s possible to save a significant amount of gas by replacing the &&
conditions with their ||
equivalent in the solution.
Use !(msg.sender == proposal.proposer || !getVotes(proposal.proposer, block.timestamp - 1) > proposal.proposalThreshold)
instead of
(msg.sender != proposal.proposer && getVotes(proposal.proposer, block.timestamp - 1) > proposal.proposalThreshold)
Use !(_from == _to || !_amount > 0)
instead of (_from != _to && _amount > 0)
Use !(msg.sender == owner || operatorApprovals[owner][msg.sender])
instead of (msg.sender != owner && !operatorApprovals[owner][msg.sender])
Use !(msg.sender == _from || operatorApprovals[_from][msg.sender] || msg.sender == tokenApprovals[_tokenId])
instead of (msg.sender != _from && !operatorApprovals[_from][msg.sender] && msg.sender != tokenApprovals[_tokenId])
Use !(!Address.isContract(_to) || ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, "") == ERC721TokenReceiver.onERC721Received.selector )
instead of
(Address.isContract(_to) &&ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, "") != ERC721TokenReceiver.onERC721Received.selector )
Use !( !Address.isContract(_to) || ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) ==ERC721TokenReceiver.onERC721Received.selector)
instead of
(Address.isContract(_to) &&ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) != ERC721TokenReceiver.onERC721Received.selector )
#0 - GalloDaSballo
2022-09-26T15:24:27Z
100 gas