Ondo Finance contest - chrisdior4's results

Institutional-Grade Finance. On-Chain. For Everyone.

General Information

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

Ondo Finance

Findings Distribution

Researcher Performance

Rank: 43/69

Findings: 1

Award: $36.24

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

QA report

Low Risk

L-NIssueInstances
[L‑01]Functions that send ether with a low level call are missing nonReentrant modifier1
[L‑02]Ownable uses single-step ownership transfer1
[L‑03]Missing zero address check in constructor2
[L‑04]Consider adding initializer modifier to _initialize** functions2

Total: 6 instances over 4 issues

Non-critical

N-CIssueInstances
[N‑01]Missing params in NatSpec2
[N‑02]Use a safe pragma statement1
[N‑03]Typos in comments3
[N‑04]Use solidity's native units for dealing with time1
[N‑05]Constants should be defined rather than using magic numbers1
[N‑06]Events are missing indexed fields3
[N‑07]Constants should be capitalized4

Total: 15 instances over 7 issues

Low Risk

[L-01] Function that sends ether with a low level call is missing nonReentrant modifier

File: 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:

[L-02] Ownable uses single-step ownership transfer

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.

[L-03] Missing zero address check in constructor

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.

[L-04] Consider adding initializer modifier to _initialize** functions

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:

Non-critical

[NC-01] Missing params in NatSpec

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
  );

[NC-02] Use a safe pragma statement

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

[NC-03] Typos in comments

File: KycRegistry.sol

sucessfully -> successfully elligible -> eligible

File: JumpRateModelV2.sol

updateable -> updatable

[NC-04] Use solidity's native units for dealing with time

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

[NC-05] Constants should be defined rather than using magic numbers

File: OndoPriceOracleV2.sol

TokenToChainlinkOracle[fToken].scaleFactor = (10 **
(36 - uint256(IERC20Like(underlying).decimals())

Lines of code:

[NC-06] Events are missing indexed fields

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.

[NC-07] Constants should be capitalized

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

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter