Platform: Code4rena
Start Date: 25/01/2022
Pot Size: $50,000 USDT
Total HM: 17
Participants: 39
Period: 3 days
Judge: LSDan
Total Solo HM: 9
Id: 79
League: ETH
Rank: 9/39
Findings: 3
Award: $1,616.67
π Selected for report: 2
π Solo Findings: 1
π Selected for report: Jujic
1556.9237 USDT - $1,556.92
Jujic
The rJoePerSec
does not have any upper or lower bounds. Values that are too large will lead to reversions in several critical functions.
function updateEmissionRate(uint256 _rJoePerSec) external onlyOwner { updatePool(); rJoePerSec = _rJoePerSec; emit UpdateEmissionRate(msg.sender, _rJoePerSec); }
Remix
Consider define upper and lower bounds on the _rJoePerSec
.
#0 - cryptofish7
2022-01-31T22:10:09Z
Confirming issue but disagree with severity.
Jujic
The functions initialize()
can be called by anyone the first time, which allows an attacker to set the address rocketJoeFactory
of the contract .
function initialize() external { require( address(rocketJoeFactory) == address(0), "RocketJoeToken: already initialized" ); rocketJoeFactory = IRocketJoeFactory(msg.sender); }
Remix
Add modifier
#0 - cryptofish7
2022-01-30T21:34:54Z
Duplicate of #68
#1 - dmvt
2022-02-22T10:44:08Z
Duplicate of #8
Jujic
!= 0 is a cheaper operation compared to > 0, when dealing with uint.
require(_amount > 0, "LaunchEvent: invalid withdraw amount");
Remix
There are several other places throughout the codebase where the same optimization can be used.
#0 - cryptofish7
2022-01-31T14:05:59Z
Duplicate of #240
π Selected for report: WatchPug
Also found by: Czar102, Dravee, Jujic, Meta0xNull, byterocket, defsec, p4st13r4, pauliax, robee, sirhashalot
Jujic
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition has been met.
There are several other places throughout the codebase where the same optimization can be used.
require( rocketJoeFactory.isRJLaunchEvent(msg.sender), "RocketJoeToken: caller is not a RJLaunchEvent" );
Shorten the revert strings to fit in 32 bytes.
#0 - cryptofish7
2022-01-31T18:54:52Z
Duplicate of #242
π Selected for report: WatchPug
Also found by: Dravee, Jujic, Rhynorater, TomFrenchBlockchain, defsec, hyh, ye0lde
Jujic
For the arithmetic operations that will never over/underflow, using the unchecked directive (Solidity v0.8 has default overflow/underflow checks) can save some gas from the unnecessary internal over/underflow checks.
if (block.timestamp > lastRewardTimestamp && joeSupply != 0) { uint256 multiplier = block.timestamp - lastRewardTimestamp;
Remix
Consider using 'unchecked' where it is safe to do so.
#0 - cryptofish7
2022-01-30T23:57:25Z
Duplicate of #233
Jujic
Using newer compiler versions and the optimizer gives gas optimizations and additional safety checks are available for free. The advantages of versions 0.8.* over <0.8.0 are: β’ Safemath by default from 0.8.0 (can be more gas efficient than library based safemath.) β’ Low level inliner : from 0.8.2, leads to cheaper runtime gas. Especially relevant when the contract has small functions. For example, OpenZeppelin libraries typically have a lot of small helper functions and if they are not inlined, they cost an additional 20 to 40 gas because of 2 extra jump instructions and additional stack operations needed for function calls. β’ Optimizer improvements in packed structs: Before 0.8.3, storing packed structs, in some cases used an additional storage read operation. After EIP-2929, if the slot was already cold, this means unnecessary stack operations and extra deploy time costs. However, if the slot was already warm, this means additional cost of 100 gas alongside the same unnecessary stack operations and extra deploy time costs. β’ Custom errors from 0.8.4, leads to cheaper deploy time cost and run time cost. Note: the run time cost is only relevant when the revert condition is met. In short, replace revert strings by custom errors.
pragma solidity ^0.8.0;
https://github.com/code-423n4/2021-10-mochi-findings/issues/34
Consider to upgrade pragma to at least 0.8.4.
#0 - cryptofish7
2022-02-10T19:48:17Z
Duplicate of #181
π Selected for report: Jujic
39.7792 USDT - $39.78
Jujic
The rJoe
variable can be cached to slightly reduce gas usage
function _safeRJoeTransfer(address _to, uint256 _amount) internal { uint256 rJoeBal = rJoe.balanceOf(address(this)); if (_amount > rJoeBal) { rJoe.transfer(_to, rJoeBal); } else { rJoe.transfer(_to, _amount); } }
Remix
Consider caching those variable for read and make sure write back to storage