Platform: Code4rena
Start Date: 18/10/2022
Pot Size: $50,000 USDC
Total HM: 13
Participants: 67
Period: 5 days
Judge: Picodes
Total Solo HM: 7
Id: 172
League: ETH
Rank: 62/67
Findings: 1
Award: $25.96
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Jeiwan
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xSmartContract, Awesome, Aymen0909, Bnke0x0, CodingNameKiki, Diana, DimSon, JC, JrNet, LeoS, RaymondFam, ReyAdmirado, Saintcode_, Shinchan, __141345__, berndartmueller, bharg4v, brgltd, carlitox477, ch0bu, chaduke, cryptostellar5, emrekocak, gogo, lukris02, martin, mcwildy, sakman, trustindistrust, zishansami
25.9629 USDC - $25.96
Instead of using the shorthand of addition/subtraction assignment operators (+=
, -=
)
it costs less to remove the shorthand ( x += y
same as x = x+y
) saves ~22 gas
For example:
Line 506: balance += tierBalanceOf[_nft][_owner][_i];
could be refactored to
Line 506: balance = balance + tierBalanceOf[_nft][_owner][_i];
Functions not internally called may have their visibility changed to external to save gas. For Example:
Line 214: ) public override {
uint
/int
Smaller Than 32 bytes (256 Bits) Incurs OverheadWhen 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.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed for example:
Line 66: function _truncate(uint8[] memory _array, uint8 _length) private pure returns (uint8[] memory) {;
Line 48: uint8 digitlength = 1;
A function with access control marked as payable will be cheaper for legitimate callers: the compiler removes checks for msg.value
, saving approximately 20
gas per function call.
For example:
Line 290 function mintFor(JBTiered721MintForTiersData[] memory _mintForTiersData) Line 291 external Line 292 override Line 293: onlyOwner
Line 321 function adjustTiers(JB721TierParams[] calldata _tiersToAdd, uint256[] calldata _tierIdsToRemove) Line 322 external Line 323 override Line 324: onlyOwner
Line 370: function setDefaultReservedTokenBeneficiary(address _beneficiary) external override onlyOwner {
Solidity version 0.8+ comes with an implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isn’t possible, some gas can be saved by using an unchecked block. For example:
for (uint256 i = 0; i < _input.length; i++) { output[i] = _input[_input.length - 1 - i]; }
could be refactored to as:
for (uint256 i = 0; i < _input.length;) { output[i] = _input[_input.length - 1 - i]; unchecked { ++i; } }
public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted
#0 - c4-judge
2022-11-04T19:57:51Z
Picodes marked the issue as grade-b