Platform: Code4rena
Start Date: 15/02/2022
Pot Size: $30,000 USDC
Total HM: 18
Participants: 35
Period: 3 days
Judge: GalloDaSballo
Total Solo HM: 8
Id: 87
League: ETH
Rank: 15/35
Findings: 3
Award: $573.75
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Czar102
Also found by: 0x1f8b, SolidityScan
455.8935 USDC - $455.89
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L164-L205
The contract was found vulnerable to Reentrancy attack. It was noticed that the function depositBribeERC20
makes an external call to another untrusted address or a contract before it resolves any effects at line "https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L187"
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.
depositBribeERC20
at https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L164-L205nonReentrant
modifierIntroduce a modifier nonreentrant
to prevent Reentrancy vulnerabilities by implementing a Check-Effects-Interactions pattern.
#0 - kphed
2022-02-17T23:25:09Z
... the function depositBribeERC20 makes an external call to another untrusted address or a contract ...
This function can only be called by those with the depositor role, which are trusted contracts owned or thoroughly vetted by the protocol.
#1 - GalloDaSballo
2022-03-06T16:29:20Z
Duplicate of #122
79.9481 USDC - $79.95
During the code assessment, we found multiple issues related to unchecked transfer and no handing of return values. Many functions call like "transfer," "deposit," "approve," etc., returns 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, it will be unrecoverable. The contract was found to be using floating pragma, which allows the contract to be compiled to multiple versions and hence can cause inconsistencies or errors on different versions. We also noticed the uses of large number literals. Although it is not a security issue but enhances readability and reduces the chance of errors or missing digits. 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. Lastly, we also noticed that the fee value, which is set by an admin, can be set to zero due lack of proper input validation.
Unchecked return value in transfer
The return value of the token transfers is not checked or validated at all in the functions shown below. This may lead to issues if there's a critical contract logic happening below the transfer that affects or manipulates the number of ether or tokens. Therefore, if the return value is not checked, the adversaries will be able to call those functions without actually transferring any ether and manipulating the token balance.
Transfer: Go to the below lines of code and we will notice that transfer https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L296 https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L297 https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L337
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/ThecosomataETH.sol#L146 https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/ThecosomataETH.sol#L164
Consider the use of safeTransfer instead of transfer that auto asserts and handles in case of transfer failure.
Unused return in approve call
The contract was found to be making an external call (approve). The function which is called is returning some value which is never used. This may lead to discrepancies and improper assumptions in the calling function.
It is recommended to make use of the return values coming from the external function that is called to make sure that the calculations following the external call are correct.
Use of Floating Pragma Version
The contract was found to be using a floating pragma which is not considered safe as it can be compiled with all the versions described.
Pragma version^0.8.0 (https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/BribeVault.sol#L2) Pragma version^0.8.0 (https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/RewardDistributor.sol#L2) Pragma version^0.8.0 (https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/ThecosomataETH.sol#L2) Pragma version^0.8.0 (https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L2)
Use strict pragma version like Pragma version 0.8.0
Missing input validation in setFee function
The function setFee
does not check if the fee value is set to zero.
An admin can set fee value to zero by mistake, and it can cause free trades and loss to the organization.
setFee
function just checks if the fee is less than feeDivisor but does not check if the fee is zero.Check if the fee is being set to zero.
Use of Large Number Literals
Integer literals are formed from a sequence of digits in the range 0-9. They are interpreted as decimals. The use of very large numbers with too many digits was detected in the code that could have been optimized using a different notation also supported by Solidity.
Literals with many digits are difficult to read and review. This may also introduce errors in the future if one of the zeroes is omitted while doing code modifications.
uint256 public constant feeDivisor = 1000000;
where 1000000 can be represnted as 10e6Scientific notation in the form of 2e10
is also supported, where the mantissa can be fractional but the exponent has to be an integer. The literal MeE
is equivalent to M * 10**E
. Examples include 2e10
, 2e10
, 2e-10
, 2.5e1
.
Reference: https://docs.soliditylang.org/en/latest/types.html#rational-and-integer-literals
Multiple missing events in critical functions
Events are inheritable members of contracts. When you call them, they cause the arguments to be stored in the transaction's log, a special data structure in the blockchain. These logs are associated with the address of the contract, which can then be used by developers and auditors to keep track of the transactions.
The contract was found to be missing these events on certain critical functions, which would make it difficult or impossible to track these transactions off-chain.
Events are used to track the transactions off-chain, and missing these events on critical functions makes it difficult to audit these logs if they're needed at a later stage.
The below functions are missing events.
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/ThecosomataETH.sol#L76-L80
The function setSlippage
is called by an admin and hence should have an event log regarding the change is slippage value.
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/ThecosomataETH.sol#L158-L165
The withdraw
function is called by an admin to withdraw funds and hence should have an event log.
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L108-L110
The function setRound
sets a new voting round by admins and hence should have an event log.
Consider emitting events for the functions mentioned above. It is also recommended to have the addresses indexed.
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-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L212-L251
Function depositBribeERC20
has address proposal
that is missing zero address checks
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L257-L290
Function depositBribe
has address input proposal
, which is lacking zero address checks.
Address zero address check to all the missing places.
#0 - kphed
2022-02-18T20:38:58Z
Besides the quoted items below, all recommendations are going to be addressed.
QA - 5
Definitely something we'll consider for larger numbers.
QA - 7
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L212-L251 Function depositBribeERC20 has address proposal that is missing zero address checks https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L257-L290 Function depositBribe has address input proposal, which is lacking zero address checks.
The proposal deadline checks would fail if proposal
was a zero address.
#1 - GalloDaSballo
2022-02-26T18:01:33Z
Disagree with floating pragma Events are informational in nature so would downgrade Agree with Magic Values not being used, but also would consider that non-critical
Overall the report has some merit, but really feels like a poor copy paste job with sub-par formatting
#2 - GalloDaSballo
2022-02-27T00:23:38Z
4/10
We found a function that was declared as public but was 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. We also noticed the contract uses power operations at a few places instead of using the exponential form directly, which would 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:
Function setRewardForwarding
https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L298-L302
Use the external
state visibility for functions that are never called from the contract.
Use of power operations instead of their exponential form
It is unnecessary to perform power operations when a number can be directly represented in an exponential form as it will save gas.
Use exponential form instead of power operations to save gas.
#0 - drahrealm
2022-02-19T07:36:34Z
Duplicate with previous similar gas optimization tips
#1 - GalloDaSballo
2022-02-26T01:21:00Z
First finding is not true, external vs public saves gas only when dealing with memory params.
Second finding is valid.
Very basic submission
#2 - GalloDaSballo
2022-02-26T01:30:02Z
2/10