Skip to content

Latest commit

 

History

History
407 lines (241 loc) · 11.2 KB

File metadata and controls

407 lines (241 loc) · 11.2 KB

Aderyn Analysis Report

This report was generated by Aderyn, a static analysis tool built by Cyfrin, a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities.

Table of Contents

Summary

Files Summary

Key Value
.sol Files 22
Total nSLOC 964

Files Details

Filepath nSLOC
src/Morpho.sol 348
src/interfaces/IERC20.sol 2
src/interfaces/IIrm.sol 6
src/interfaces/IMorpho.sol 119
src/interfaces/IMorphoCallbacks.sol 16
src/interfaces/IOracle.sol 4
src/libraries/ConstantsLib.sol 8
src/libraries/ErrorsLib.sol 27
src/libraries/EventsLib.sol 48
src/libraries/MarketParamsLib.sol 10
src/libraries/MathLib.sol 25
src/libraries/SafeTransferLib.sol 23
src/libraries/SharesMathLib.sol 19
src/libraries/UtilsLib.sol 23
src/libraries/periphery/MorphoBalancesLib.sol 79
src/libraries/periphery/MorphoLib.sol 46
src/libraries/periphery/MorphoStorageLib.sol 76
src/mocks/ERC20Mock.sol 33
src/mocks/FlashBorrowerMock.sol 18
src/mocks/IrmMock.sol 15
src/mocks/OracleMock.sol 8
src/mocks/interfaces/IERC20.sol 11
Total 964

Issue Summary

Category No. of Issues
High 2
Low 10

High Issues

H-1: Contract Name Reused in Different Files

When compiling contracts with certain development frameworks (for example: Truffle), having contracts with the same name across different files can lead to one being overwritten.

2 Found Instances
  • Found in src/interfaces/IERC20.sol Line: 9

     interface IERC20 {}
  • Found in src/mocks/interfaces/IERC20.sol Line: 4

     interface IERC20 {

H-2: Reentrancy: State change after external call

Changing state after an external call can lead to re-entrancy attacks.Use the checks-effects-interactions pattern to avoid this issue.

1 Found Instances
  • Found in src/Morpho.sol Line: 361

    State is changed at: position[id][borrower].borrowShares -= repaidShares.toUint128(), market[id].totalBorrowShares -= repaidShares.toUint128(), market[id].totalBorrowAssets = UtilsLib.zeroFloorSub(market[id].totalBorrowAssets, repaidAssets).toUint128(), position[id][borrower].collateral -= seizedAssets.toUint128(), market[id].totalBorrowAssets -= badDebtAssets.toUint128(), market[id].totalSupplyAssets -= badDebtAssets.toUint128(), market[id].totalBorrowShares -= badDebtShares.toUint128(), position[id][borrower].borrowShares = 0

                 uint256 collateralPrice = IOracle(marketParams.oracle).price();

Low Issues

L-1: Centralization Risk

Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.

5 Found Instances
  • Found in src/Morpho.sol Line: 95

         function setOwner(address newOwner) external onlyOwner {
  • Found in src/Morpho.sol Line: 104

         function enableIrm(address irm) external onlyOwner {
  • Found in src/Morpho.sol Line: 113

         function enableLltv(uint256 lltv) external onlyOwner {
  • Found in src/Morpho.sol Line: 123

         function setFee(MarketParams memory marketParams, uint256 newFee) external onlyOwner {
  • Found in src/Morpho.sol Line: 139

         function setFeeRecipient(address newFeeRecipient) external onlyOwner {

L-2: ecrecover Signature Malleability

The ecrecover function is susceptible to signature malleability. This means that the same message can be signed in multiple ways, allowing an attacker to change the message signature without invalidating it. This can lead to unexpected behavior in smart contracts, such as the loss of funds or the ability to bypass access control. Consider using OpenZeppelin's ECDSA library instead of the built-in function.

1 Found Instances
  • Found in src/Morpho.sol Line: 453

             address signatory = ecrecover(digest, signature.v, signature.r, signature.s);

L-3: Unsafe ERC20 Operation

ERC20 functions may not behave as expected. For example: return values are not always meaningful. It is recommended to use OpenZeppelin's SafeERC20 library.

3 Found Instances
  • Found in src/libraries/SafeTransferLib.sol Line: 23

                 address(token).call(abi.encodeCall(IERC20Internal.transfer, (to, value)));
  • Found in src/libraries/SafeTransferLib.sol Line: 32

                 address(token).call(abi.encodeCall(IERC20Internal.transferFrom, (from, to, value)));
  • Found in src/mocks/FlashBorrowerMock.sol Line: 22

             IERC20(token).approve(address(MORPHO), assets);

L-4: Unspecific Solidity Pragma

Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of pragma solidity ^0.8.0;, use pragma solidity 0.8.0;

11 Found Instances
  • Found in src/interfaces/IERC20.sol Line: 2

     pragma solidity >=0.5.0;
  • Found in src/interfaces/IIrm.sol Line: 2

     pragma solidity >=0.5.0;
  • Found in src/interfaces/IMorpho.sol Line: 2

     pragma solidity >=0.5.0;
  • Found in src/interfaces/IMorphoCallbacks.sol Line: 2

     pragma solidity >=0.5.0;
  • Found in src/interfaces/IOracle.sol Line: 2

     pragma solidity >=0.5.0;
  • Found in src/libraries/ConstantsLib.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/mocks/ERC20Mock.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/mocks/FlashBorrowerMock.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/mocks/IrmMock.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/mocks/OracleMock.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/mocks/interfaces/IERC20.sol Line: 2

     pragma solidity ^0.8.0;

L-5: Literal Instead of Constant

Define and use constant variables instead of using literals. If the same constant literal value is used multiple times, create a constant state variable and reference it throughout the contract.

4 Found Instances
  • Found in src/libraries/periphery/MorphoLib.sol Line: 25

             return uint256(morpho.extSloads(slot)[0] >> 128);
  • Found in src/libraries/periphery/MorphoLib.sol Line: 35

             return uint256(morpho.extSloads(slot)[0] >> 128);
  • Found in src/libraries/periphery/MorphoLib.sol Line: 45

             return uint256(morpho.extSloads(slot)[0] >> 128);
  • Found in src/libraries/periphery/MorphoLib.sol Line: 55

             return uint256(morpho.extSloads(slot)[0] >> 128);

L-6: Empty require() / revert() Statement

Use descriptive reason strings or custom errors for revert paths.

1 Found Instances
  • Found in src/mocks/FlashBorrowerMock.sol Line: 20

             require(msg.sender == address(MORPHO));

L-7: Internal Function Used Only Once

Instead of separating the logic into a separate function, consider inlining the logic into the calling function. This can reduce the number of function calls and improve readability.

1 Found Instances
  • Found in src/libraries/MathLib.sol Line: 32

         function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {

L-8: Uninitialized Local Variable

Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.

1 Found Instances
  • Found in src/Morpho.sol Line: 549

             for (uint256 i; i < nSlots;) {

L-9: State Change Without Event

There are state variable changes in this function but no event is emitted. Consider emitting an event to enable offchain indexers to track the changes.

2 Found Instances
  • Found in src/mocks/ERC20Mock.sol Line: 12

         function setBalance(address account, uint256 amount) public virtual {
  • Found in src/mocks/OracleMock.sol Line: 9

         function setPrice(uint256 newPrice) external {

L-10: Unchecked Return

Function returns a value but it is ignored. Consider checking the return value.

1 Found Instances
  • Found in src/mocks/FlashBorrowerMock.sol Line: 22

             IERC20(token).approve(address(MORPHO), assets);