Platform: Code4rena
Start Date: 16/02/2023
Pot Size: $144,750 USDC
Total HM: 17
Participants: 154
Period: 19 days
Judge: Trust
Total Solo HM: 5
Id: 216
League: ETH
Rank: 113/154
Findings: 1
Award: $61.26
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: GalloDaSballo
Also found by: 0x3b, 0xAgro, 0xSmartContract, 0xTheC0der, 0xackermann, 0xnev, 0xsomeone, ABA, BRONZEDISC, Bjorn_bug, Bnke0x0, Breeje, Co0nan, CodeFoxInc, CodingNameKiki, DadeKuma, DeFiHackLabs, IceBear, Josiah, Kaysoft, Lavishq, MohammedRizwan, PaludoX0, PawelK, Phantasmagoria, Raiders, RaymondFam, Rickard, Rolezn, Sathish9098, SleepingBugs, SuperRayss, UdarTeam, Udsen, Viktor_Cortess, arialblack14, ast3ros, bin2chen, brgltd, btk, catellatech, ch0bu, chaduke, chrisdior4, codeislight, cryptonue, delfin454000, descharre, dontonka, emmac002, fs0c, hacker-dom, hansfriese, imare, lukris02, luxartvinsec, martin, matrix_0wl, peanuts, rbserver, shark, tnevler, trustindistrust, tsvetanovv, vagrant, yongskiws, zzzitron
61.2601 USDC - $61.26
L-N | Issue |
---|---|
[Lโ01] | Single-step ownership transfer pattern is dangerous |
[Lโ02] | Decimals() not part of ERC20 standard |
[Lโ03] | Open TODO in the code |
[Lโ04] | Using vulnerable dependency of OpenZeppelin |
[Lโ05] | Usage of ecrecover should be replaced with usage of OpenZeppelin's ECDSA library |
Total: 5 issues
N-N | Issue |
---|---|
[Nโ01] | Solidity safe pragma best practices are not used |
[Nโ02] | NatSpecs are missing |
[Nโ03] | Events, structs and custom errors declaration |
[Nโ04] | Event is missing indexed fields |
[Nโ05] | Typos in the comments |
[Nโ06] | Redundant code |
[Nโ07] | Use of magic number |
[Nโ08] | Interchangeable usage of uint and uint256 in in BorrowerOperations.sol |
[Nโ09] | Lines are too long |
Total: 9 issues
File: CollateralConfig.sol
Inheriting from OpenZeppelin's Ownable
contract means you are using a single-step ownership transfer pattern. If an admin provides an incorrect address for the new owner this will result in none of the onlyOwner
marked methods being callable again. The better way to do this is to use a two-step ownership transfer approach, where the new owner should first claim its new rights before they are transferred.
import "./Dependencies/Ownable.sol";
Lines of code:
Use OpenZeppelin's Ownable2Step
instead of Ownable
File: CollateralConfig.sol
The initialize
method is looping through _collaterals
array and fetching tokens decimals. However decimals() is not part of the official ERC20 standard and might fall for tokens that do not implement it. While in practice it is very unlikely, as usually most of the tokens implement it, this should still be considered as a potential issue.
uint256 decimals = IERC20(collateral).decimals();
Lines of code:
Consider using a helper function to safely retrieve token decimals.
There is an open TODO in StabilityPool.sol
this implies changes that might not be audited. Resolve it or remove it.
/* TODO tess3rac7 unused var, but previously included in ETHGainWithdrawn event log.
/* TODO tess3rac7 unused var, but previously included in ETHGainWithdrawn event log.
Lines of code:
The package.json configuration file says that the project is using 4.7.3 of OZ which has a not last update version:
Use patched versions.
Latest non vulnerable version 4.8.0.
File: LUSDToken.sol
Signature malleability is one of the potential issues with ecrecover. Even though it is not a threat to the current implementation using the highest security standards is always good.
address recoveredAddress = ecrecover(digest, v, r, s);
Lines of code:
Import ECDSA library. Replace the usage of ecrecover with the ECDSA.recover functionality.
Always use a stable pragma to be certain that you deterministically compile the Solidity code to the same bytecode every time. Also IStargateReceiver and IStargateRouter interfaces are using an old compiler version - upgrade it to a newer version, use the same pragma statement throughout the whole codebase.
File: CollateralConfig.sol
@notice, @param and @return fields are missing throughout the codebase in a lot of external functions. NatSpec documentation is essential for better understanding of the code by developers and auditors and is strongly recommended, add it to each struct, enum, function, interface and contract. Please refer to the NatSpec format and follow the guidelines outlined there.
Most of the events and structs are declared in the implementation contracts when It is a best practice to be declared in the interface not in the implementation contract.
File: CollateralConfig.sol
Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event
should use three indexed
fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
event CollateralWhitelisted(address _collateral, uint256 _decimals, uint256 _MCR, uint256 _CCR); event CollateralRatiosUpdated(address _collateral, uint256 _MCR, uint256 _CCR);
Lines of code:
lenghts
-> lengths
elswhere
-> elsewhere
calculcate
-> calculate
occured
-> occurred
File: BorrowerOperations.sol
./Dependencies/console.sol";
import is not used and should be removed.
File: BorrowerOperations.sol
Constant variables instead of magic numbers can help keep the code easier to read and maintain.
troveManagerCached.closeTrove(msg.sender, _collateral, 2);
Lines of code:
File: ActivePool.sol
Although it is understandable that these numbers are regarding the BPS value, constant variables instead of magic numbers can help keep the code easier to read and maintain.
require(_bps <= 10_000, "Invalid BPS value");
require(_driftBps <= 500, "Exceeds max allowed value of 500 BPS");
require(_treasurySplit + _SPSplit + _stakingSplit == 10_000, "Splits must add up to 10000 BPS");
Lines of code:
BorrowerOperations.sol
Consider using only one approach throughout the codebase, e.g. only uint or only uint256.
Usually lines in source code are limited to 80 characters. Todayโs screens are much larger so itโs reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length. Reference: https://docs.soliditylang.org/en/v0.8.10/style-guide.html#maximum-line-length
In ActivePool.sol
, there are multiple instances of this issue. Here are couple of examples:
vars.percentOfFinalBal = vars.finalBalance == 0 ? uint256(-1) : vars.currentAllocated.mul(10_000).div(vars.finalBalance); ... if (vars.percentOfFinalBal > vars.yieldingPercentage && vars.percentOfFinalBal.sub(vars.yieldingPercentage) > yieldingPercentageDrift) {
Lines of code:
#0 - c4-judge
2023-03-09T19:07:18Z
trust1995 marked the issue as grade-b
#1 - c4-sponsor
2023-03-28T21:31:36Z
0xBebis marked the issue as sponsor acknowledged