Platform: Code4rena
Start Date: 03/02/2022
Pot Size: $75,000 USDC
Total HM: 42
Participants: 52
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 21
Id: 83
League: ETH
Rank: 33/52
Findings: 3
Award: $226.75
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ShadowyNoobDev
Also found by: 0xw4rd3n, CertoraInc, Czar102, GalloDaSballo, Heartless, IllIllI, Jujic, Randyyy, Rhynorater, Sleepy, SolidityScan, ckksec, kirk-baird, leastwood, pauliax, peritoflores, reassor
7.97 USDC - $7.97
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConcurRewardPool.sol#L34-L40
The contract was found vulnerable to Reentrancy attack. It was noticed that the function claimRewards
makes an external call to another untrusted address or a contract before it resolves any effects and unlike other functions, it is lacking nonReentrant
modifier.
If the attacker controls the untrusted contract, they may be able to call back to the original function, repeating interactions that would have otherwise not run after the effects were resolved.
Reentrancy vulnerabilities can lead to various critical outcomes such as token stealing and burning. Adversaries may exploit the bug to mint tokens without any limitations or extract all the tokens out of the contract.
claimRewards
is performing an external call at the line https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConcurRewardPool.sol#L37 but is missing the nonReentrant
modifier during the function call.Introduce a modifier nonreentrant
to prevent Reentrancy vulnerabilities by implementing a Check-Effects-Interactions pattern.
#0 - r2moon
2022-02-18T03:11:53Z
#1 - GalloDaSballo
2022-04-18T23:20:58Z
Duplicate of #260
🌟 Selected for report: hickuphh3
Also found by: 0x1f8b, 0xw4rd3n, BouSalman, CertoraInc, Czar102, Dravee, IllIllI, Randyyy, Rhynorater, Ruhum, ShadowyNoobDev, Sleepy, SolidityScan, WatchPug, bitbopper, cccz, cryptphi, csanuragjain, defsec, gzeon, harleythedog, hubble, hyh, kenta, kirk-baird, leastwood, mtz, pauliax, peritoflores, rfa, robee, samruna, throttle, wuwe1, ye0lde
151.7966 USDC - $151.80
During the code assessment, we found multiple issues related to unchecked transfer and no handing of return values. Many functions calls like transfer, deposit, approve, etc., return some value after the function call. Handling these calls is important to prevent unexpected outcomes. Apart from that, we found multiple functions which were missing zero address checks. It is advised to add a zero address check at all possible functions setting an address. In solidity, any error caused to set the value to default, and for an address variable, the default value is zero address. Hence any fund or privilege gets pointed to zero address, and it will be unrecoverable. During the code review, we noticed boolean comparison, which is redundant as it is auto compared when an if statement is used; hence it can be removed. We also noticed missing events in many critical functions. Events are important for logging purposes. Hence it is recommended to add events and indexed events at all possible function calls for better logging.
Unchecked return value in transfer
Several tokens do not revert in case of failure and return false if the return value is not handled. Any error which caused the failure on transfer will go unnoticed.
Consider the use of safeTransfer instead of transfer that auto asserts and handles in case of transfer failure.
Unused return
The return value of an external call is not stored in a local or state variable which can cause improper assumptions as the return value was not handled/processed.
Go to the below lines
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L243
We will notice the return value of deposit
call is not stored and handled.
Also, at line 79-80
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/USDMPegRecovery.sol#L79-L80
We will notice the return value of the approve
function call is not used or handled.
Ensure that all the return values of the function calls are used.
Multiple functions Lacking Zero address checks
Address type parameters should include a zero-address check; otherwise contract functionality may become inaccessible, or tokens burned forever.
Tokens may become inaccessible or burnt forever without a zero-address check.
Below is the list of functions lacking zero address checks
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConcurRewardPool.sol#L15-L17
Missing zero address checks in _notifier
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L69-L72
Missing zero address checks in _treasury
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L82-L84
Missing zero address checks in _treasury
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L86-L88
Missing zero address checks in _claimContract
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L78-L80
Missing zero address checks in _depositor
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/StakingRewards.sol#L37-L47
Missing zero address checks in _rewardsDistribution
_rewardsToken
& _stakingToken
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/VoteProxy.sol#L11-L13
Missing zero address checks in _auctioneer
Address zero address check to all the missing places.
Meaningless comparison to boolean constant
Comparison to boolean constant is meanless and not required. Boolean constants can be used directly and do not need to be compared to true or false.
if (auctioneer.isWinningSignature(_hash, _signature) == true)
which can simply be if (auctioneer.isWinningSignature(_hash, _signature)
Use if (auctioneer.isWinningSignature(_hash, _signature)
instead.
Multiple missing events in critical functions
Events are important and should be emitted for tracking this off-chain for all important functions.
The below functions are missing events.
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConcurRewardPool.sol#L15-L17
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L69-L72
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L82-L84
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L86-L88
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L94-L96 (Need to check how it works)
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L62
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L78-L80
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/Shelter.sol#L28-L30
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/StakingRewards.sol#L37-L47
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/VoteProxy.sol#L11-L13
Address zero address check to all the missing places.
#0 - GalloDaSballo
2022-04-27T13:55:10Z
#149 Non-critical finding
Unchecked return value in transfer Valid
Unused return Disagree because impl is know and these are known to revert on failure
Multiple functions Lacking Zero address checks Agree, I appreciate the list
Meaningless comparison to boolean constant Gas
Multiple missing events in critical functions Non-critical
Pretty decent report
#1 - GalloDaSballo
2022-04-27T15:07:21Z
2++
🌟 Selected for report: WatchPug
Also found by: 0x0x0x, 0x1f8b, 0x510c, 0xNot0rious, 0xngndev, BouSalman, CertoraInc, Dravee, Heartless, IllIllI, Jujic, Randyyy, Ruhum, ShadowyNoobDev, Sleepy, SolidityScan, Tomio, bitbopper, csanuragjain, defsec, gzeon, hickuphh3, kenta, mtz, pauliax, peritoflores, rfa, robee, sabtikw, throttle, wuwe1, ye0lde
66.977 USDC - $66.98
During the code review, we found that few state variables that were declared as private
could be marked as constant
as they were not expected to be updated. Constant variables consume lesser gas than private variables. Also, we found a few functions that were declared as public but were never internally used. Such functions can always be marked as external
instead of public
as external
functions consume lesser gas in comparison to public
functions.
It was also noticed that the ordering of variables in structs was in random order. Structs perform variable packing, and hence it is recommended to go from lower bytes to higher bytes as the lower bytes get packed together to save gas.
The contract was also found to be using the safeMath library, which is redundant if version solidity compiler version 0.8.0 and above is used as it has enough built-in features to prevent buffer overflow attacks and perform safer arithmetic calculations. It is advised to remove the safeMath library as they are super expensive in terms of gas consumption.
State variables that could be declared constant
Constant state variables should be declared constant to save gas.
The below variables concurPerBlock
_concurShareMultiplier
_perMille
can be used as constants instead of private.
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L50
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L56
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L57
concurPerBlock
_concurShareMultiplier
_perMille
can be used as constants instead of private to save gas.
Functions that can be external instead of public
Public functions that are never called by a contract should be declared external in order to conserve gas.
Smart Contracts are required to have effective Gas usage as they cost real money, and each function should be monitored for the amount of gas it costs to make it gas efficient.
Public
functions cost more Gas than external
functions.
The following functions can be declared external: https://github.com/code-423n4/2022-02-concur/blob/main/contracts/ConvexStakingWrapper.sol#L93-L118 https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L86-L101 https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L127-L132
Use the external
state visibility for functions that are never called from the contract.
Ordering of structs
Structs are packed, and arrangement matters for packing, which in turn affects the gas used. The ordering should be from lower to higher space consumption so packing can be done.
Use the ordering as below, switching depositFeeBP
to 2nd place instead of last.
IERC20 depositToken; // Address of LP token contract. uint16 depositFeeBP; // Deposit fee in basis points uint allocPoint; // How many allocation points assigned to this pool. to distribute per block. uint lastRewardBlock; // Last block number that distribution occurs. uint accConcurPerShare; // Accumulated per share, times multiplier. See below.
Use of Safemath
Safemath module is considered very gas expensive. It was useful before solidity 0.8.0. After the 0.8.0 version, solidity auto handles buffer overflow, and hence safeMath can be avoided.
The MasterChef.sol
file is using safeMath which is
https://github.com/code-423n4/2022-02-concur/blob/main/contracts/MasterChef.sol#L10
Avoid using safeMath module to save gas
#0 - GalloDaSballo
2022-04-04T14:25:43Z
3 * 2100 = 6300
Will not save gas
Will not save gas
Valid but no poc on gas saved so 0
No deets on how this save gas
Total Gas saved 6300
Would recommend the warden to check their report on a MD previewer to make it look slightly better