Platform: Code4rena
Start Date: 26/05/2023
Pot Size: $100,000 USDC
Total HM: 0
Participants: 33
Period: 14 days
Judge: leastwood
Id: 241
League: ETH
Rank: 13/33
Findings: 1
Award: $813.40
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rbserver
Also found by: 0x73696d616f, 0xTheC0der, 0xdeadbeef, 0xhacksmithh, Bauchibred, GalloDaSballo, KKat7531, Madalad, MohammedRizwan, Rolezn, SAAJ, SanketKogekar, Sathish9098, VictoryGod, brgltd, btk, codeslide, descharre, hunter_w3b, jauvany, kaveyjoe, ladboy233, nadin, niser93, shealtielanz, souilos, trysam2003, yongskiws
813.4016 USDC - $813.40
Total Low issues |
---|
Risk | Issues Details | Number |
---|---|---|
[L-01] | Critical changes should use-two step procedure | 4 |
[L-02] | Avoid using tx.origin | 2 |
[L-03] | No Storage Gap for Upgradeable contracts | 5 |
[L-04] | Loss of precision due to rounding | 1 |
[L-05] | Integer overflow by unsafe casting | 1 |
[L-06] | Add address(0) check for the critical changes | 1 |
[L-07] | Multiple Pragma used | All Contracts |
[L-08] | Missing Event for initialize | 5 |
The following contracts inherits the Openzeppelin Ownable
contract which have a function that allows the owner to transfer the ownership to a different address. If the owner accidentally uses an invalid address for which they do not have the private key, then the system will gets locked.
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
Consider inheriting Ownable2Step
instead.
A similar issue was reported in a previous contest and was assigned a severity of medium: code-423n4/2021-06-realitycards-findings#105
tx.origin
tx.origin
is a global variable in Solidity that returns the address of the account that sent the transaction.
Using the variable could make a contract vulnerable if an authorized account calls a malicious contract. You can impersonate a user using a third party contract.
if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {
if (msg.sender != tx.origin) {
Avoid using tx.origin
.
For upgradeable contracts, inheriting contracts may introduce new variables. In order to be able to add new variables to the upgradeable contract without causing storage collisions, a storage gap should be added to the upgradeable contract.
function initialize() public initializer {
function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)
function initialize(bool _paused) public initializer {
function initialize(
function initialize() public initializer {
Consider adding a storage gap at the end of the upgradeable contract:
/** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap;
Solidity may truncate the result due to the nature of arithmetics and rounding errors. Hence we must multiply before dividing to prevent such loss in precision
((_config.maxResourceLimit / _config.elasticityMultiplier) * _config.elasticityMultiplier) == _config.maxResourceLimit,
Multiplication should always be performed before division to avoid loss of precision.
Keep in mind that the version of solidity used, despite being greater than 0.8, does not prevent integer overflows during casting, it only does so in mathematical operations.
It is necessary to safely convert between the different numeric types.
params.prevBaseFee = uint128(uint256(newBaseFee));
Use OpenZeppelin safeCast library.
address(0)
check for the critical changesCheck of address(0)
to protect the code from (0x0000000000000000000000000000000000000000)
address problem just in case. This is best practice or instead of suggesting that they verify _address != address(0)
, you could add some good NatSpec comments explaining what is valid and what is invalid and what are the implications of accidentally using an invalid address.
function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner { _setUnsafeBlockSigner(_unsafeBlockSigner); bytes memory data = abi.encode(_unsafeBlockSigner); emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data); }
Add checks for address(0)
when assigning values to address state variables.
Solidity pragma versions should be exactly same in all contracts. Currently some contracts use 0.8.15
and others use ^0.8.0
Use one version for all contracts.
Events help non-contract tools to track changes, and events prevent users from being surprised by changes Issuing event-emit during initialization is a detail that many projects skip.
function initialize() public initializer {
function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)
function initialize(bool _paused) public initializer {
function initialize(
function initialize() public initializer {
Add Event-Emit
#0 - c4-judge
2023-06-16T13:43:58Z
0xleastwood marked the issue as grade-b