Platform: Code4rena
Start Date: 21/06/2022
Pot Size: $50,000 USDC
Total HM: 31
Participants: 99
Period: 5 days
Judges: moose-code, JasoonS, denhampreen
Total Solo HM: 17
Id: 139
League: ETH
Rank: 83/99
Findings: 1
Award: $34.71
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xmint, 8olidity, ACai, Bnke0x0, Chom, ElKu, Fabble, Fitraldys, FudgyDRS, Funen, GalloDaSballo, GimelSec, IllIllI, JC, Kaiziron, Lambda, Limbooo, MiloTruck, Noah3o6, Nyamcil, Picodes, PwnedNoMore, Randyyy, RedOneN, Sm4rty, StErMi, TomJ, Tomio, TrungOre, UnusualTurtle, Waze, _Adam, aga7hokakological, ajtra, antonttc, asutorufos, bardamu, c3phas, defsec, delfin454000, exd0tpy, fatherOfBlocks, hansfriese, ignacio, joestakey, kenta, ladboy233, m_Rassska, mics, minhquanym, oyc_109, pashov, reassor, robee, s3cunda, sach1r0, saian, sashik_eth, scaraven, sikorico, simon135, slywaters
34.7125 USDC - $34.71
Solidity does not recognize null as a value, so uint variables are initialized to zero. Setting a uint variable to zero is redundant and can waste gas.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L636 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L637
Remove the redundant zero initialization
uint256 i;
instead of uint256 i = 0;
Combining require statement conditions with && logic uses unnecessary gas. It is better to split up each part of the logical statement into a separate require statements
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L55 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L56 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L57 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L58 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L59 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L60 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L285 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L286 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L287 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L305 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L361 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L362 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L575 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L606 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L612
Use separate require statements instead of concatenating with &&
Using > 0
uses slightly more gas than using != 0
. Use != 0
when comparing uint variables to zero, which cannot hold values below zero
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L83 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L96 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L118 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L305 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L326 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L363 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L392 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L410 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L415 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L470 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L533 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L572 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L604 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L223
Replace > 0
with != 0
to save gas
Comparing a value to zero can be done using the iszero
EVM opcode. This can save gas
Source from t11s https://twitter.com/transmissions11/status/1474465495243898885
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L85 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L280 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L435 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L219
Use the assembly iszero
evm opcode to compare values to zero
Use unchecked math when there is no overflow risk to save gas. Before index is decreased in remove it is checked for zero condition. This means index will not underflow and can be unchecked.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L716
Add unchecked around math that can't overflow for gas savings. In Solidity before 0.8.0, use the normal math operators instead of safe math functions.
Identifying a function as payable saves gas. Functions that have a modifier like onlyOwner cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L141 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L157 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L167 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L177 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L187 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L197 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L207 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L217 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L226 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L235 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L370 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L769 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/BatchRequests.sol#L81 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/BatchRequests.sol#L89 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L92
Add payable to these functions for gas savings
Identifying a constructor as payable saves gas. Constructors should only be called by the admin or deployer and should not mistakenly receive ETH. Constructors can be payable to save gas.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Migration.sol#L18
Add payable to these functions for gas savings
An internal function can save gas vs. a modifier. A modifier inlines the code of the original function but an internal function does not.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L24
Use internal functions in place of modifiers to save gas.
Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L28 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L187 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L197 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L207 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L674 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L743 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L744 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/BatchRequests.sol#L37
Replace bool variables with uints
From the solidity docs
When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L32 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L227 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/YieldyStorage.sol#L18 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/YieldyStorage.sol#L23 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/StakingStorage.sol#L41 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/StakingStorage.sol#L42 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L36 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L113 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L636 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L637
Replace smaller int or uint variables with uint256 variables
A solidity version before 0.8.X is used. The latest release of solidity includes changes that can provide gas savings. The improvements include:
Source https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#upgrade-to-at-least-084
Use solidity release 0.8.13 with Yul IR pipeline and other improvements for gas savings
Solidity errors introduced in version 0.8.4 can save gas on revert conditions https://blog.soliditylang.org/2021/04/21/custom-errors/ https://twitter.com/PatrickAlphaC/status/1505197417884528640
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L58 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L59 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L83 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L96 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L187 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L190 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L210 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L249 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L257 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L279 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Yieldy.sol#L286 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L54 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L118 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L143 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L408 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L410 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L527 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L572 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L574 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L586 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L604 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L605 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L611 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L644 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L676 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L25 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L44 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L61 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L62 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L68 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L94 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L105 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L163 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L170 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L192 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserve.sol#L215 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Migration.sol#L20
Replace require blocks with new solidity errors described in https://blog.soliditylang.org/2021/04/21/custom-errors/
The comparison operators >= and <= use more gas than >, <, or ==. Replacing the >= and ≤ operators with a comparison operator that has an opcode in the EVM saves gas
The existing code is https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Staking.sol#L713
if (balance <= staked) { epoch.distribute = 0; } else { epoch.distribute = balance - staked; }
A simple comparison can be used for gas savings by reversing the logic
if (balance > staked) { epoch.distribute = balance - staked; } else { epoch.distribute = 0; }
Replace the comparison operator and reverse the logic to save gas using the suggestions above
Many constant variables are public, but changing the visibility of these variables to private or internal can save gas.
Locations where this was found include https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/YieldyStorage.sol#L10 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/YieldyStorage.sol#L11 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/YieldyStorage.sol#L13 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserveStorage.sol#L9 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/LiquidityReserveStorage.sol#L10 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/StakingStorage.sol#L39 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Migration.sol#L14 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Migration.sol#L15 https://github.com/code-423n4/2022-06-yieldy/tree/main/src/contracts/Migration.sol#L16
Declare some public variables as private or internal to save gas
The contracts are all written entirely in solidity. Writing contracts with vyper instead of solidity can save gas.
Source https://twitter.com/eiber_david/status/1515737811881807876 doggo demonstrates https://twitter.com/fubuloubu/status/1528179581974417414?t=-hcq_26JFDaHdAQZ-wYxCA&s=19
Write some or all of the contracts in vyper to save gas