Platform: Code4rena
Start Date: 27/10/2022
Pot Size: $33,500 USDC
Total HM: 8
Participants: 96
Period: 3 days
Judge: kirk-baird
Total Solo HM: 1
Id: 176
League: ETH
Rank: 29/96
Findings: 2
Award: $143.48
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: robee
Also found by: 0x007, 0x1f8b, 0x52, 0xDjango, 0xNazgul, 0xSmartContract, 8olidity, Awesome, B2, Bnke0x0, Chom, Diana, Dravee, JTJabba, Jeiwan, Josiah, Lambda, Mathieu, Picodes, RaoulSchaffranek, RaymondFam, RedOneN, ReyAdmirado, Rolezn, Ruhum, Sm4rty, Tricko, Trust, Waze, __141345__, a12jmx, adriro, ajtra, brgltd, c3phas, carlitox477, cccz, ch0bu, chaduke, chrisdior4, corerouter, cryptonue, csanuragjain, ctf_sec, cylzxje, delfin454000, dic0de, djxploit, horsefacts, imare, jayphbee, jwood, ktg, ladboy233, leosathya, lukris02, minhtrng, neko_nyaa, oyc_109, pashov, peritoflores, rbserver, rvierdiiev, shark, tnevler, yixxas
19.6449 USDC - $19.64
protocalFeeRatio --> protocolFeeRatio (this is a mistake in a statevar and it has 6 instances)
taget --> target
balacne --> balance
reards --> rewards
Minmum --> Minimum (4 instances)
Platfrom --> Platform
Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it’s not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
The best-practice layout for a contract should follow the following order: state variables, events, modifiers, constructor and functions. Function ordering helps readers identify which functions they can call and find constructor and fallback functions easier. Functions should be grouped according to their visibility and ordered as: constructor, receive function (if exists), fallback function (if exists), external, public, internal, private.
wrong place for struct
external should be after each other first then public then internal then private
There are multiple occasions where certain numbers have been hardcoded, either in variables or in the code itself. Large numbers can become hard to read.
Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant in a library. If the variable is a local cache of another contract’s value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don’t get out of sync. https://medium.com/coinmonks/gas-cost-of-solidity-library-functions-dbe0cedd4678
minDelegationTime
state var does not change and its always 1 week, change it to constant to improve readability of the contract
Event is never emitted, consider adding emit in the position intended
IncreasePledgeTargetVotes
Using old versions of Solidity prevents benefits of bug fixes and newer security checks. Using the latest versions might make contracts susceptible to undiscovered compiler bugs
#0 - c4-judge
2022-11-12T00:06:30Z
kirk-baird marked the issue as grade-b
🌟 Selected for report: c3phas
Also found by: 0x1f8b, 0xNazgul, 0xRoxas, 0xSmartContract, 0xbepresent, Amithuddar, Awesome, B2, Bnke0x0, Dravee, KoKo, Mathieu, Picodes, RaymondFam, RedOneN, ReyAdmirado, RockingMiles, Ruhum, SadBase, SooYa, Waze, __141345__, adriro, ajtra, ballx, carlitox477, ch0bu, cylzxje, djxploit, durianSausage, emrekocak, erictee, gogo, halden, horsefacts, imare, indijanc, karanctf, leosathya, lukris02, neko_nyaa, oyc_109, peiw, sakman, shark, skyle, tnevler
123.8403 USDC - $123.84
Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmaccess (100 gas) with a PUSH32 (3 gas).
votingEscrow
delegationBoost
The instances below point to the second+ access of a state variable within a function. Caching of a state variable replace each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.
mostly the if statements gonna pass, so its better to cache minAmountRewardToken[rewardToken]
at this line
consider caching pledgeParams.endTimestamp
earlier before this line because the if statement mostly gonna pass
pledgeParams.rewardToken
same here
If the variable is only accessed once, it’s cheaper to use the state variable directly that one time, and save the 3 gas the extra stack assignment would spend
amount
slope
totalDelegatedAmount
remainingDuration
rewardPerVoteDiff
creator
unchecked {}
for subtractions where the operands cannot underflow because of a previous if
statementif(a <= b); x = b - a => if(a <= b); unchecked { x = b - a } this will stop the check for overflow and underflow so it will save gas
endTimestamp is bigger than block.timestamp because its checked in line 229. (endTimestamp got pledgeParams.endTimestamp value in line 233):
checked in line 383
checked in line 426
checked in line 429
<x> += <y>
costs more gas than <x> = <x> + <y>
for state variablesUsing the addition operator instead of plus-equals saves gas
||
in if statementThere is a chance that the first part will be true so the second part doesn’t need to be checked, so it is better to use the part that we have instead of the part that needs to be called.
Use a solidity version of at least 0.8.13 to get the ability to use using for
with a list of free functions
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. 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 https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed
#0 - c4-judge
2022-11-12T00:06:06Z
kirk-baird marked the issue as grade-b
#1 - c4-judge
2022-11-12T01:20:57Z
kirk-baird marked the issue as grade-a