Platform: Code4rena
Start Date: 11/01/2023
Pot Size: $60,500 USDC
Total HM: 6
Participants: 69
Period: 6 days
Judge: Trust
Total Solo HM: 2
Id: 204
League: ETH
Rank: 43/69
Findings: 1
Award: $36.24
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: CodingNameKiki
Also found by: 0x1f8b, 0x52, 0x5rings, 0xAgro, 0xSmartContract, 0xcm, 0xkato, 2997ms, Aymen0909, BClabs, BPZ, BRONZEDISC, Bauer, Bnke0x0, Deekshith99, IllIllI, Josiah, Kaysoft, RaymondFam, Rolezn, SaeedAlipoor01988, Tajobin, Udsen, Viktor_Cortess, adriro, arialblack14, betweenETHlines, btk, chaduke, chrisdior4, cryptphi, csanuragjain, cygaar, defsec, descharre, erictee, gzeon, hansfriese, horsefacts, joestakey, koxuan, lukris02, luxartvinsec, nicobevi, oyc_109, pavankv, peanuts, rbserver, scokaf, shark, tnevler, tsvetanovv, zaskoh
36.2377 USDC - $36.24
L-N | Issue | Instances |
---|---|---|
[L‑01] | Functions that send ether with a low level call are missing nonReentrant modifier | 1 |
[L‑02] | Ownable uses single-step ownership transfer | 1 |
[L‑03] | Missing zero address check in constructor | 2 |
[L‑04] | Consider adding initializer modifier to _initialize** functions | 2 |
Total: 6 instances over 4 issues
N-C | Issue | Instances |
---|---|---|
[N‑01] | Missing params in NatSpec | 2 |
[N‑02] | Use a safe pragma statement | 1 |
[N‑03] | Typos in comments | 3 |
[N‑04] | Use solidity's native units for dealing with time | 1 |
[N‑05] | Constants should be defined rather than using magic numbers | 1 |
[N‑06] | Events are missing indexed fields | 3 |
[N‑07] | Constants should be capitalized | 4 |
Total: 15 instances over 7 issues
call
is missing nonReentrant
modifierFile: CashFactory.sol
Add a nonReentrant modifier to this external function that is making a low level call in order to be sure 100% that reentrancy can not occur:
(bool success, bytes memory ret) = address(exCallData[i].target).call{ value: exCallData[i].value }(exCallData[i].data);
Lines of code:
File: OndoPriceOracleV2.sol
import "contracts/cash/external/openzeppelin/contracts/access/Ownable.sol";
The OndoPriceOracleV2 contract inherits from Ownable and the owner is the one who can set couple of important features such as Oracle, Price of an fToken contract's underlying asset, etc.. The Ownable contract implements single-step ownership transfer, which means that if a wrong address was passed when transferring ownership or admin rights it can mean that role is lost forever.
Recommendation:
It is a best practice to use two-step ownership transfer pattern, meaning ownership transfer gets to a "pending" state and the new owner should claim his new rights, otherwise the old owner still has control of the contract. Consider using OpenZeppelin's Ownable2Step contract.
File: KycRegistry.sol
constructor( address admin, address _sanctionsList ) EIP712("OndoKYCRegistry", "1") { _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(REGISTRY_ADMIN, admin); sanctionsList = ISanctionsList(_sanctionsList);
Lines of code:
Consider adding zero address check for the two address parameters in the constructor.
It's recommended to add initializer modifier to the initialize function of upgradable contracts to make sure they are called only once in the lifetime of a contract.
Files: CCash.sol and CErc20.sol
Lines of code respectively:
Params name
and ticker
are not described in the NatSpec for event CashDeployed in CashFactory.sol
* @dev Event emitted when upgradable cash is deployed * * @param proxy The address for the proxy contract * @param proxyAdmin The address for the proxy admin contract * @param implementation The address for the implementation contract */ event CashDeployed( address proxy, address proxyAdmin, address implementation, string name, string ticker );
Always use stable pragma statement to lock the compiler version. Also there are different versions of the compiler used throughout the codebase, use only one. Finally consider upgrading the version to a newer one to use bugfixes and optimizations in the compiler.
Most of the contracts are using a fairly new version - 0.8.16, but for example JumpRateModelV2.sol is using floatable 0.5.16.
Update the pragma statement to stable 0.8.17
File: KycRegistry.sol
sucessfully
-> successfully
elligible
-> eligible
File: JumpRateModelV2.sol
updateable
-> updatable
Solidity provides some native units for dealing with time. We can use the following units: seconds, minutes, hours, days, weeks and years. These units will convert to a uint of the number of seconds in that specific length of time.
File: OndoPriceOracleV2.sol
uint256 public maxChainlinkOracleTimeDelay = 90000;
Lines of code:
Consider changing 90000
to 25 hours
File: OndoPriceOracleV2.sol
TokenToChainlinkOracle[fToken].scaleFactor = (10 ** (36 - uint256(IERC20Like(underlying).decimals())
Lines of code:
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).
File: ICashManager.sol
Events FeeRecipientSet
, AssetRecipientSet
, AssetSenderSet
are missing indexed fields, consider adding them.
Files: CTokenInterfacesModified.sol and CTokenInterfacesModifiedCash.sol
uint internal constant borrowRateMaxMantissa = 0.0005e16; ... uint internal constant reserveFactorMaxMantissa = 1e18;
Lines of code:
uint internal constant borrowRateMaxMantissa = 0.0005e16; ... uint internal constant reserveFactorMaxMantissa = 1e18;
Lines of code:
#0 - c4-judge
2023-01-22T17:56:42Z
trust1995 marked the issue as grade-b