Platform: Code4rena
Start Date: 14/09/2022
Pot Size: $50,000 USDC
Total HM: 25
Participants: 110
Period: 5 days
Judge: hickuphh3
Total Solo HM: 9
Id: 162
League: ETH
Rank: 39/110
Findings: 2
Award: $142.83
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: cccz
Also found by: Respx, Saintcode_, csanuragjain, fatherOfBlocks, pashov, unforgiven
90.0028 USDC - $90.00
https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/rewards/StakingRewards.sol#L34 https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/rewards/StakingRewards.sol#L213 https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/rewards/StakingRewards.sol#L218
Add a validation on line 218 that validates that you cannot withdraw tokens from rewardsToken.
#0 - MiguelBits
2022-09-21T19:34:41Z
I forked these contracts from synthetix
They do the same, which is something I did not change: https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol
Please state your argument with test cases, because Synthetix is well tested.
#1 - HickupHH3
2022-10-17T04:52:17Z
While technically valid, and I consider this to be a possible rug-pull vector on rewards, one could view this as a feature to sweep out the rewards.
User funds aren't locked because they can use the withdraw()
function instead of exit()
.
Downgrading to non-crit QA
#2 - HickupHH3
2022-10-17T04:52:37Z
part of #164
#3 - HickupHH3
2022-11-05T02:56:46Z
dup #49.
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x4non, 0xNazgul, 0xSmartContract, 0xc0ffEE, 0xkatana, Aymen0909, Bnke0x0, Deivitto, Diana, JAGADESH, KIntern_NA, Lambda, MiloTruck, R2, RaymondFam, Respx, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Samatak, Sm4rty, SnowMan, Tomio, Tomo, WilliamAmbrozic, _Adam, __141345__, ajtra, ak1, async, c3phas, ch0bu, cryptostellar5, d3e4, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gianganhnguyen, gogo, ignacio, imare, jag, jonatascm, leosathya, lukris02, malinariy, oyc_109, pashov, pauliax, peanuts, peiw, prasantgupta52, robee, rokinot, rotcivegaf, rvierdiiev, seyni, simon135, slowmoses, sryysryy, tnevler, zishansami
52.8286 USDC - $52.83
Controller.sol
L93/211 - Less gas cost is generated by doing if(bool) or if(!bool) than by doing bool == true or bool == false, this generates a double validation.
L200/206 - VaultFactory.getVaults(marketIndex) is executed twice, once to obtain the length and once to obtain only the getter. Much less gas could be generated by doing a single query bringing it into memory to the getter and then on line 200 using the length of the variable in memory.
L283 - as we try to subtract the execution time of the tx, minus the startedAt of the oracle, that value will always be less, therefore it could become unchecked so that an extra validation of underflows is not executed.
PegOracle.sol
**SemiFungibleVault.sol **
Vault.sol
L80/96/217/314 - Less gas cost is generated by doing if(bool) or if(!bool) than by doing bool == true or bool == false, this generates a double validation.
L187 - It is less expensive to validate that uint(number) != 0 than uint(number) > 0
L227 - since we try to subtract entitledShares - feeValue and we know that feeValue is a derivative of entitledShares, we can be sure that an underflow will not occur, therefore we can not validate them with unchecked.
L443 - When a uint256 value is impossible to generate overflow, as for example in a loop for i++, it can be returned unchecked and ++i.
L443 - When we create a variable and we want it to have its base value, it is not necessary to set that value, since this would imply a double setting.
L443 - When we are using a for and the length of the array is constantly consulted inside, it would be less expensive to create a variable in memory of the length of the array.
VaultFactory.sol
L159 - When we create a variable and we want it to have its base value, it is not necessary to set that value, since this would imply a double setting.
L195 - It is less expensive does variable = variable + 1; which variable += 1;
rewards/StakingRewards.sol
L36 - When we create a variable and we want it to have its base value, it is not necessary to set that value, since this would imply a double setting.
L119/134 - It is less expensive to validate that uint(number) != 0 than uint(number) > 0
L228 - The message shown in the require has a size greater than 32 bytes, this generates an extra gas cost that could be avoided by having a message less than 32 characters.
rewards/RewardsFactory.sol
#0 - HickupHH3
2022-11-08T09:23:44Z
L200/206 - VaultFactory.getVaults(marketIndex) is executed twice, once to obtain the length and once to obtain only the getter. Much less gas could be generated by doing a single query bringing it into memory to the getter and then on line 200 using the length of the variable in memory.
L29/36 - priceFeed1.decimals() is executed twice. Much less gas could be generated by doing a single query bringing it into memory to the uint and then on lines 29 and 36 using the value in memory.
L159 - When we create a variable and we want it to have its base value, it is not necessary to set that value, since this would imply a double setting.
These saw significant gas savings.