Platform: Code4rena
Start Date: 04/11/2022
Pot Size: $42,500 USDC
Total HM: 9
Participants: 88
Period: 4 days
Judge: 0xean
Total Solo HM: 2
Id: 180
League: ETH
Rank: 44/88
Findings: 2
Award: $65.42
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x1f8b
Also found by: 0xSmartContract, 0xc0ffEE, Aymen0909, B2, Deivitto, Josiah, KingNFT, Rahoz, RaymondFam, RedOneN, ReyAdmirado, Trust, ajtra, aviggiano, brgltd, c7e7eff, cryptonue, ctf_sec, delfin454000, djxploit, lukris02, peanuts, rvierdiiev, shark, simon135, slowmoses, tnevler, trustindistrust
44.2869 USDC - $44.29
Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (threefields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
NatSpec is incomplete in many functions. It's a best practice to complete it to a major understanding.
ECCMath.sol#L18 ECCMath.sol#L37 ECCMath.sol#L51 ECCMath.sol#L60
Replace the magic numbers for a constant that describe the meaning of it.
SizeSealed.sol#L157 SizeSealed.sol#L241 SizeSealed.sol#L249 SizeSealed.sol#L251 SizeSealed.sol#L309
ECCMath.sol#L51 SizeSealed.sol#L451
To a best understanding the struct definition should be at the begining of the contract.
#0 - c4-judge
2022-11-10T02:53:04Z
0xean marked the issue as grade-b
🌟 Selected for report: 0x1f8b
Also found by: 0xSmartContract, 0xdeadbeef, Aymen0909, B2, Bnke0x0, Deivitto, Diana, Dinesh11G, JC, RaymondFam, ReyAdmirado, Rolezn, Sathish9098, TomJ, ajtra, aviggiano, chaduke, cryptostellar5, djxploit, gianganhnguyen, gogo, halden, karanctf, leosathya, lukris02, mcwildy, oyc_109, ret2basic, skyle, slowmoses
21.132 USDC - $21.13
In the following example (optimizer = 10000) it's possible to demostrate that I = I + X cost less gas than I += X in state variable.
contract Test_Optimization { uint256 a = 1; function Add () external returns (uint256) { a = a + 1; return a; } } contract Test_Without_Optimization { uint256 a = 1; function Add () external returns (uint256) { a += 1; return a; } }
With this optimization it's possible to save 116 gas
SizeSealed.sol#L294 SizeSealed.sol#L373
abi.encode will apply ABI encoding rules. Therefore all elementary types are padded to 32 bytes and dynamic arrays include their length. Therefore it is possible to also decode this data again (with abi.decode) when the type are known.
abi.encodePacked will only use the only use the minimal required memory to encode the data. E.g. an address will only use 20 bytes and for dynamic arrays only the elements will be stored without length. For more info see the Solidity docs for packed mode
For the input of the keccak method it is important that you can ensure that the resulting bytes of the encoding are unique. So if you always encode the same types and arrays always have the same length then there is no problem. But if you switch the parameters that you encode or encode multiple dynamic arrays you might have conflicts.
For example:
abi.encodePacked(address(0x0000000000000000000000000000000000000001), uint(0)) encodes to the same as abi.encodePacked(uint(0x0000000000000000000000000000000000000001000000000000000000000000), address(0))
and
abi.encodePacked(uint, uint) encodes to the same as abi.encodePacked(uint, uint)
Therefore these examples will also generate the same hashes even so they are different inputs.
On the other hand you require less memory and therefore in most cases abi.encodePacked uses less gas than abi.encode.
SizeSealed.sol#L467 ECCMath.sol#L26 ECCMath.sol#L61
Use unchecked { i++; } or unchecked{ ++i; } when it's not possible to overflow to save gas.
SizeSealed.sol#L244 SizeSealed.sol#L302
Use calldata instead of memory in a function parameter when you are only to read the data can save gas by storing it in calldata
SizeSealed.sol#L217 ECCMath.sol#L25 ECCMath.sol#L37 ECCMath.sol#L51 ECCMath.sol#L60
<x> * 2 is equivalent to <x> << 1 and <x> / 2 is the same as <x> >> 1. The MUL and DIV opcodes cost 5 gas, whereas SHL and SHR only cost 3 gas. In the code there are some division by 256 that is the same than <x> >> 8.
- uint256[] memory seenBidMap = new uint256[]((bidIndices.length/256)+1); + uint256[] memory seenBidMap = new uint256[]((bidIndices.length >> 8)+1);
- uint256 bitmapIndex = bidIndex / 256; - uint256 bitmapIndex = bidIndex >> 8;
- uint256 quoteBought = FixedPointMathLib.mulDivDown(baseAmount, a.data.lowestQuote, a.data.lowestBase); - uint256 refundedQuote = b.quoteAmount - quoteBought; + uint256 refundedQuote = b.quoteAmount - FixedPointMathLib.mulDivDown(baseAmount, a.data.lowestQuote, a.data.lowestBase);
#0 - c4-judge
2022-11-10T02:25:30Z
0xean marked the issue as grade-b