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: 102/133
Findings: 1
Award: $12.87
🌟 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.8681 USDC - $12.87
++i/--i
costs less gas than post-increment i++/i--
Saves 6 gas per loop in a for loop
Total instances of this issue: 1
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
src/ERC20/ERC20PermitPermissionedMint.sol 84: for (uint i = 0; i < minters_array.length; i++){
++i/i++
should be placed in unchecked blocks to save gas as it is impossible for them to overflow in for and while loopsUnchecked keyword is available in solidity version 0.8.0
or higher and can be applied to iterator variables to save gas.
Saves more than 30 gas
per loop.
Total instances of this issue: 5
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
src/ERC20/ERC20PermitPermissionedMint.sol 84: for (uint i = 0; i < minters_array.length; i++){
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L129
src/frxETHMinter.sol 129: for (uint256 i = 0; i < numDeposits; ++i) {
instance #3 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L63
src/OperatorRegistry.sol 63: for (uint256 i = 0; i < arrayLength; ++i) {
instance #4 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L84
src/OperatorRegistry.sol 84: for (uint256 i = 0; i < times; ++i) {
instance #5 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L114
src/OperatorRegistry.sol 114: for (uint256 i = 0; i < original_validators.length; ++i) {
<array>.length
) need not be looked up in every iteration of a for-loopReading array length at each iteration of the loop takes total 6 gas (3 for mload and 3 to place memory_offset) in the stack.
Caching the array.length
saves around 3 gas
per iteration.
Total instances of this issue: 2
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
src/ERC20/ERC20PermitPermissionedMint.sol 84: for (uint i = 0; i < minters_array.length; i++){
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L114
src/OperatorRegistry.sol 114: for (uint256 i = 0; i < original_validators.length; ++i) {
x += y
costs more gas than x = x + y
for state variablesTotal instances of this issue: 2
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L97
src/frxETHMinter.sol 97: currentWithheldETH += withheld_amt;
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L72
lib/ERC4626/src/xERC4626.sol 72: storedTotalAssets += amount;
unchecked {}
block where the variable cannot underflow because of a previous require()
require(a <= b); x = b - a
==> require(a <= b); unchecked { x = b - a }
Total instances of this issue: 1
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L168
src/frxETHMinter.sol 168: currentWithheldETH -= amount;
if (<x> == true) ==> if (<x>) if (<x> == false) => if (!<x>)
Total instances of this issue: 3
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L46
src/ERC20/ERC20PermitPermissionedMint.sol 46: require(minters[msg.sender] == true, "Only minters");
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L68
src/ERC20/ERC20PermitPermissionedMint.sol 68: require(minters[minter_address] == false, "Address already exists");
instance #3 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L78
src/ERC20/ERC20PermitPermissionedMint.sol 78: require(minters[minter_address] == true, "Address nonexistant");
Since the default value is already zero, overwriting is not required.
Saves 8 gas
per instance.
Total instances of this issue: 6
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
src/ERC20/ERC20PermitPermissionedMint.sol 84: for (uint i = 0; i < minters_array.length; i++){
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L94
src/frxETHMinter.sol 94: uint256 withheld_amt = 0;
instance #3 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L129
src/frxETHMinter.sol 129: for (uint256 i = 0; i < numDeposits; ++i) {
instance #4 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L63
src/OperatorRegistry.sol 63: for (uint256 i = 0; i < arrayLength; ++i) {
instance #5 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L84
src/OperatorRegistry.sol 84: for (uint256 i = 0; i < times; ++i) {
instance #6 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L114
src/OperatorRegistry.sol 114: for (uint256 i = 0; i < original_validators.length; ++i) {
Gas usage becomes higher with uint/int smaller than 256 bits because EVM operates on 32 bytes and uses additional operations to reduce the size from 32 bytes to the target size.
Total instances of this issue: 12
instance #1 Permalink: https://github.com/code-423n4/2022-09-frax/blob/main/src/sfrxETH.sol#L42-L45
src/sfrxETH.sol 42: constructor(ERC20 _underlying, uint32 _rewardsCycleLength) 43: ERC4626(_underlying, "Staked Frax Ether", "sfrxETH") 44: xERC4626(_rewardsCycleLength) 45: {}
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L24
lib/ERC4626/src/xERC4626.sol 24: uint32 public immutable rewardsCycleLength;
instance #3 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L27
lib/ERC4626/src/xERC4626.sol 27: uint32 public lastSync;
instance #4 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L30
lib/ERC4626/src/xERC4626.sol 30: uint32 public rewardsCycleEnd;
instance #5 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L33
lib/ERC4626/src/xERC4626.sol 33: uint192 public lastRewardAmount;
instance #6 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L37
lib/ERC4626/src/xERC4626.sol 37: constructor(uint32 _rewardsCycleLength) {
instance #7 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L48
lib/ERC4626/src/xERC4626.sol 48: uint192 lastRewardAmount_ = lastRewardAmount;
instance #8 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L49
lib/ERC4626/src/xERC4626.sol 49: uint32 rewardsCycleEnd_ = rewardsCycleEnd;
instance #9 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L50
lib/ERC4626/src/xERC4626.sol 50: uint32 lastSync_ = lastSync;
instance #10 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L79
lib/ERC4626/src/xERC4626.sol 79: uint192 lastRewardAmount_ = lastRewardAmount;
instance #11 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L80
lib/ERC4626/src/xERC4626.sol 80: uint32 timestamp = block.timestamp.safeCastTo32();
instance #12 Link: https://github.com/code-423n4/2022-09-frax/blob/main/lib/ERC4626/src/xERC4626.sol#L89
lib/ERC4626/src/xERC4626.sol 89: uint32 end = ((timestamp + rewardsCycleLength) / rewardsCycleLength) * rewardsCycleLength;
!= 0
costs less gas than > 0
in a require() statementSaves 6 gas per instance for solidity version less than 0.8.12.
Total instances of this issue: 2
instance #1 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L79
src/frxETHMinter.sol 79: require(sfrxeth_recieved > 0, 'No sfrxETH was returned');
instance #2 Link: https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L126
src/frxETHMinter.sol 126: require(numDeposits > 0, "Not enough ETH in contract");