Platform: Code4rena
Start Date: 27/05/2022
Pot Size: $75,000 USDC
Total HM: 20
Participants: 58
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 15
Id: 131
League: ETH
Rank: 54/58
Findings: 1
Award: $62.68
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, Chom, Dravee, Fitraldys, Funen, Kaiziron, MiloTruck, Picodes, Randyyy, RoiEvenHaim, SecureZeroX, Sm4rty, SmartSek, StyxRave, Tadashi, Tomio, Waze, asutorufos, berndartmueller, c3phas, catchup, csanuragjain, defsec, delfin454000, djxploit, fatherOfBlocks, gzeon, hake, hansfriese, oyc_109, robee, sach1r0, sashik_eth, scaraven, simon135
62.6774 USDC - $62.68
Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop. This saves gas.
This was found in many places https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/RewardHandler.sol#L42 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L82 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/zaps/PoolMigrationZap.sol#L22 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/zaps/PoolMigrationZap.sol#L39 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L56 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L94 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L116 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L259
Cache the array length before the for loop
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-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L91 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L92 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L137 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L139 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L254 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L301 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/RewardHandler.sol#L63 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L117 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/LpGauge.sol#L68 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/LpGauge.sol#L114 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L84 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L575 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L589 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L602 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L88 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L104 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L125 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L147 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/KeeperGauge.sol#L140 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L107 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L129 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L158 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L171 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L197
Replace > 0
with != 0
to save gas
For loops that use i++ do not need to use safemath for this operation because the loop would run out of gas long before this point. Making this addition operation unsafe using unchecked saves gas. This is already used in many places with i = i.uncheckedInc()
.
Sample code to make the for loop increment unsafe
for (uint i = 0; i < length; i = unchecked_inc(i)) { // do something that doesn't change the value of i } function unchecked_inc(uint i) returns (uint) { unchecked { return i + 1; } }
Idea borrowed from https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#the-increment-in-for-loop-post-condition-can-be-made-unchecked
There is one loop and that can use this change https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/zaps/PoolMigrationZap.sol#L22
Make the increment in for loops unsafe 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
There are many places where a value is compared to zero https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L59 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L271 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L97 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L99 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L101 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/zaps/PoolMigrationZap.sol#L57 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/utils/Preparable.sol#L28 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L61 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L69 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L75 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrowRevocable.sol#L53 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L144 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L105 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L133 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L165 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L174 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L183 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L496 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L514 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L522 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L106
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.
These subtractions do not need to be checked for underflows because there is a require earlier that confirms the underflow will not happen. Use the uncheckedSub
function
https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L124
https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L338
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 onlyGovernance or onlyAuthorizedToPause cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas.
There are many functions that have the auth modifier in the contracts. Some examples are https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L58 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L70 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L37 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L41 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L45 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L50 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L54 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L111 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L99 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L104 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L147 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L58 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L70 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L92 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L136 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L167 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L342 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L408 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L435 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L449 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L469 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L86 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L92 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L33 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L62 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L81 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L89 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L63 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L70 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L81 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L216 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L229 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L239 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L256 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/AddressProvider.sol#L278 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L75 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L82 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L87
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.
Many modifiers can use this change https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L27 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/AuthorizationBase.sol#L16 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/AuthorizationBase.sol#L24 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/AuthorizationBase.sol#L32 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/AuthorizationBase.sol#L40 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/utils/Pausable.sol#L9 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/utils/Pausable.sol#L14 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L47 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/KeeperGauge.sol#L39
Use internal functions in place of modifiers to save gas.
Solidity version 0.8.10 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
Many immutable variables are public, but changing the visibility of any of these variables to private or internal can save gas.
https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/BkdLocker.sol#L42 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/RewardHandler.sol#L20 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/RewardHandler.sol#L21 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/access/RoleManager.sol#L25 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrowRevocable.sol#L28 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/BkdToken.sol#L14 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/LpGauge.sol#L19 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/LpGauge.sol#L20 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/LpGauge.sol#L21 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L33 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L37 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/VestedEscrow.sol#L38 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L25 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L26 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L30 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L31 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L32 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L36 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L37 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L38 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L44 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/Minter.sol#L55 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/InflationManager.sol#L24 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L20 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmGauge.sol#L30 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/KeeperGauge.sol#L30 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/KeeperGauge.sol#L31 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L19 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L20 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L21 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L24 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/AmmConvexGauge.sol#L25 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/Controller.sol#L21 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L43 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L45 https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/StakerVault.sol#L46
Declare some public variables as private or internal to save gas
Using calldata instead of memory for function arguments saves gas sometimes. This can happen when a function is called externally and the memory array values are kept in calldata
and copied to memory
during ABI decoding (using the opcode calldataload
and mstore
). If the array is used in a for loop, arr[i]
accesses the value in memory using a mload
. If calldata is used instead, then instead of going via memory, the value is directly read from calldata
using calldataload
. That is, there are no intermediate memory operations that carries this value.
One case of function arguments using memory instead of calldata can use this improvement to save gas https://github.com/code-423n4/2022-05-backd/tree/main/protocol/contracts/tokenomics/FeeBurner.sol#L43
Related DoS issue https://twitter.com/danielvf/status/1519381832592199681
Change function arguments from memory to calldata
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
Write some or all of the contracts in vyper to save gas
#0 - chase-manning
2022-06-07T21:44:33Z
Lol "Write contracts in vyper" 🤣
#1 - GalloDaSballo
2022-06-16T21:14:37Z
Would save 3 gas per instance 3 * 8 = 24
Works only for requires, saves 3 gas Only 9 instances were requires
3 * 9 = 27
Saves 25 gas
25
Saves 2 gas per the discussion in #27 2 * 22 = 44
Would save 20 gas per instance
40
It would save gas but personally would not count it as it does change the contract behaviour even if by a small margin (also changes UX on Metamask)
Indeed does save gas on deployment
Valid but hard to quantify
Would save gas by removing functionality
Finding is valid but in lack of math I'm not going to add it
Same as above, I guess we'll burn hundreds of thousands of dollars of work and rewrite in vyper
I think this report could have been great had the warden done more comparison of the real code with improvements
Total Gas Saved: 160