Platform: Code4rena
Start Date: 22/09/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 133
Period: 3 days
Judge: 0xean
Total Solo HM: 2
Id: 165
League: ETH
Rank: 125/133
Findings: 1
Award: $12.81
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x4non, 0x5rings, 0xA5DF, 0xNazgul, 0xSmartContract, 0xmatt, 0xsam, Amithuddar, Aymen0909, B2, Ben, Bnke0x0, Chom, CodingNameKiki, Deivitto, Diana, Fitraldys, Funen, IllIllI, JAGADESH, JC, Metatron, Ocean_Sky, PaludoX0, Pheonix, RaymondFam, ReyAdmirado, RockingMiles, Rohan16, Rolezn, Satyam_Sharma, Sm4rty, SnowMan, SooYa, Tagir2003, TomJ, Tomio, Triangle, V_B, Waze, __141345__, ajtra, albincsergo, asutorufos, aysha, beardofginger, bobirichman, brgltd, bulej93, bytera, c3phas, ch0bu, cryptostellar5, cryptphi, d3e4, delfin454000, dharma09, drdr, durianSausage, emrekocak, erictee, fatherOfBlocks, gogo, got_targ, imare, jag, karanctf, ladboy233, leosathya, lukris02, medikko, mics, millersplanet, natzuu, neko_nyaa, oyc_109, peanuts, prasantgupta52, rbserver, ret2basic, rokinot, ronnyx2017, rotcivegaf, sach1r0, samruna, seyni, slowmoses, tnevler, wagmi, zishansami
12.811 USDC - $12.81
Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L79 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L87-88 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L122-140 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L160 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L167-171 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L193 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L200 https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L137 https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L182 https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L203 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L66-68 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L77-78 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L95 https://github.com/code-423n4/2022-09-frax/blob/main/src/Utils/Owner.sol#L22
Replace require() with if (a != b) revert ERROR()
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional store, along with additional overhead for computing memory offset, etc.
https://github.com/code-423n4/2022-09-frax/blob/main/src/Utils/Owner.sol#L22 https://github.com/code-423n4/2022-09-frax/blob/main/src/Utils/Owner.sol#L29 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L167
Use error codes or shorten the error messages
Solidity version 0.8+ comes with an implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isn’t possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block
The majority of Solidity for loops increment a uint256 variable that starts at 0. These increment operations never need to be checked for over/underflow because the variable will never reach the max number of uint256 (will run out of gas long before that happens). The default over/underflow check wastes gas in every iteration of virtually every for loop. eg.
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
e.g Let's work with a sample loop below.
for(uint256 i; i < 10; i++){ //doSomething }
can be written as shown below.
for(uint256 i; i < 10;) { // loop logic unchecked { i++; } }
Using != for uint Comparision saves gas compared to >
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L79 https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L126
Replace > 0 with != 0
uint variables are by default assigned 0 value. Explicitly assigning it 0, costs more gas
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L94
Remove explicit assignment of uint variables
For all the public functions, the input parameters are copied to memory automatically, and it costs gas. If your function is only called externally, then you should explicitly mark it as external. External function’s parameters are not copied into memory but are read from calldata directly. This small optimization in your solidity code can save you a lot of gas when the function input parameters are huge.
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L82 https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L92 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L65 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L76 https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L94
Make public functions external if not called within the contract.