Platform: Code4rena
Start Date: 04/01/2023
Pot Size: $60,500 USDC
Total HM: 15
Participants: 105
Period: 5 days
Judge: gzeon
Total Solo HM: 1
Id: 200
League: ETH
Rank: 91/105
Findings: 1
Award: $36.50
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xSmartContract
Also found by: 0x1f8b, 0xAgro, 0xdeadbeef0x, 0xhacksmithh, 2997ms, Atarpara, Bnke0x0, Diana, HE1M, IllIllI, Josiah, Kalzak, Lirios, MalfurionWhitehat, MyFDsYours, Raiders, RaymondFam, Rolezn, SaharDevep, Sathish9098, Udsen, Viktor_Cortess, adriro, ast3ros, betweenETHlines, btk, chaduke, chrisdior4, cryptostellar5, csanuragjain, giovannidisiena, gz627, hl_, horsefacts, joestakey, juancito, ladboy233, lukris02, nadin, oyc_109, pauliax, peanuts, prady, sorrynotsorry, zaskoh
36.5015 USDC - $36.50
Statements inside require and assert should not change state through any function call or keyword. The contract was found to be making state changes inside the require or assert statements.
It is recommended to not make any state changes inside assert or require statements and to always follow the pattern of check-effects-interactions. assert should only be used to check invariants and should be replaced with require for user input and return values.
Solidity source files indicate the versions of the compiler they can be compiled with using a pragma directive at the top of the solidity file. This can either be a floating pragma or a specific compiler 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.
The following affected files were found to be using floating pragma:- ^0.8.12
It is recommended to use a fixed pragma version, as future compiler versions may handle certain language constructions in a way the developer did not foresee.
Using a floating pragma may introduce several vulnerabilities if compiled with an older version.
The developers should always use the exact Solidity compiler version when designing their contracts as it may break the changes in the future.
Instead of ^0.8.12
use pragma solidity 0.8.7
, which is a stable and recommended version right now.
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 BaseSmartAccount
was found to be missing these events on the function validateUserOp
which would make it difficult or impossible to track these transactions off-chain.
Consider emitting events for the functions mentioned above. It is also recommended to have the addresses indexed.
The Smart Contract is using inline assembly - specifically the instructions of the CALL family such as delegatecall
and staticcall
. It should be manually checked for data handling and that it does not overwrite the input data by writing output data over it. In case the arbitrary address is passed inside the call, the return value may differ from the expected one.
Depending on how the CALL
is handled in the code, if the output is being overwritten on the same memory space as the input, consider saving the output to a separate area of memory.
A require
statement was detected with an empty message. It takes two parameters and the message part is optional. This is shown to the user when and if the require
statement evaluates to false
. This message gives more information about the statement and why it gave a false
response.
It is recommended to add a descriptive message, no longer than 32 bytes, inside the require statement to give more detail to the user about why the condition failed.
Contracts often need access to time values to perform certain types of functionality. Values such as block.timestamp
and block.number
can be used to determine the current time or the time delta. However, they are not recommended for most use cases.
For block. Number
, as Ethereum block times are generally around 14 seconds, the delta between blocks can be predicted. The block times, on the other hand, do not remain constant and are subject to change for a number of reasons, e.g., fork reorganizations and the difficulty bomb.
Due to variable block times, block.number
should not be relied on for precise calculations of time.
Smart contracts should be written with the idea that block values are not precise, and their use can have unexpected results. Alternatively, oracles can be used.
Events are essential for tracking off-chain data and when the event paraemters are indexed
they can be used as filter options which will help getting only the specific data instead of all the logs.
Consider adding indexed
keyword to crucial event parameters that could be used in off-chain tracking. Do remember that the indexed
keyword costs more gas.
The function ecrecover
allows you to convert a valid signature into a different valid signature without requiring knowledge of the private key. It is usually not a problem unless you use signatures to identify items or require them to be uniquely recognizable.
Therefore, depending on the function of the code, this may lead to discrepancies and faulty logic.
It is recommended to use OpenZeppelin’s ECDSA library that has a wrapper around ecrecover that mitigates this issue. The data signer can be recovered using ECDSA.recover, and its address can be compared to verify the signature.
#0 - c4-judge
2023-01-22T15:15:38Z
gzeon-c4 marked the issue as grade-b
#1 - c4-sponsor
2023-02-09T12:44:40Z
livingrockrises marked the issue as sponsor confirmed