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.
- Summary
- High Issues
- Low Issues
- L-1: Centralization Risk
- L-2:
ecrecoverSignature Malleability - L-3: Unsafe ERC20 Operation
- L-4: Unspecific Solidity Pragma
- L-5: Literal Instead of Constant
- L-6: Empty
require()/revert()Statement - L-7: Internal Function Used Only Once
- L-8: Uninitialized Local Variable
- L-9: State Change Without Event
- L-10: Unchecked Return
| Key | Value |
|---|---|
| .sol Files | 22 |
| Total nSLOC | 964 |
| 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 |
| Category | No. of Issues |
|---|---|
| High | 2 |
| Low | 10 |
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
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 = 0uint256 collateralPrice = IOracle(marketParams.oracle).price();
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 {
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);
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);
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;
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);
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));
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) {
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;) {
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
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);