Skip to content

Latest commit

 

History

History
224 lines (175 loc) · 21.3 KB

090.md

File metadata and controls

224 lines (175 loc) · 21.3 KB

Innocent Turquoise Barracuda

High

Critical Initialization Parameters Not Validated Leading to Potential Contract Lockup

Summary

The DLOImplementation contract's initialize function fails to validate critical parameters during initialization, which could lead to a permanently broken contract state. Specifically, it doesn't validate:

  1. The aggregator contract address cannot be zero address
  2. The principle token address cannot be zero address
  3. The accepted collaterals array cannot be empty
  4. The maxLTVs array length must match accepted collaterals array length

This was confirmed through Echidna testing which demonstrated all these validations can fail.

Root Cause

in https://github.com/sherlock-audit/2024-11-debita-finance-v3/blob/main/Debita-V3-Contracts/contracts/DebitaV3Loan.sol#L156

There is no valid check of the paramters that are sent to the contract when initializing and this could make it contact useless for example no principle token which is literally what the user is trying to lend out.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

  • HIGH SEVERITY
  • If deployed with invalid parameters, the contract becomes permanently unusable since:
    • acceptLendingOffer would fail due to zero address aggregator
    • Token transfers would fail due to zero address principle token
    • No collateral could be accepted due to empty collateral array
    • Inconsistent array lengths could cause out-of-bounds access or revert
  • The contract cannot be reinitialized due to the initializer modifier, making these issues permanent

PoC

contract DLOImplementationEchidnaTest is DLOImplementation {
    event Log (string value);

    // Initialize Echidna with dummy addresses and parameters to set up the contract state
    constructor() {

        uint[] memory _ratios = new uint[](1);

        address[] memory _acceptableCollateral = new address[](0);
        address[] memory _oracleIDSCollateral = new address[](2);
        bool[] memory _oracleActivated = new bool[](1);
        uint[] memory _maxLTVs = new uint[](2);

        _oracleIDSCollateral[0] = address(0);
//        _acceptableCollateral[0] = address(0);
        _oracleActivated[0] = true;
        _maxLTVs[0] = 0;
        _maxLTVs[1] = 0;


        initialize(
            address(0), // _aggregatorContract
            true, // _perpetual
            _oracleActivated,
            true, // _lonelyLender
            _maxLTVs,
            5, // _apr
            31536000, // _maxDuration (1 year)
            86400, // _minDuration (1 day)
            msg.sender, // _owner
            address(0), // _principle
            _acceptableCollateral, // _aedCollaterals
            _oracleIDSCollateral, // _oraclCollateral
            _ratios, // _ratio
            address(0), // _oracleID_Principle
            0 // _startedLendingAmount
        );
    }


    function checkInvalidInitializer() public returns (bool)  {

        if (aggregatorContract == address(0)){
            emit Log("Aggregator contract  is address(0)");
        }
        if (lendInformation.principle == address(0)){
            emit Log("principle is address(0)");

        }

        if (lendInformation.acceptedCollaterals.length == 0){
            emit Log("acceptedCollaterals is zero in length");
        }

        if (lendInformation.maxLTVs.length != lendInformation.acceptedCollaterals.length){
            emit Log("lendInformation.maxLTVs.length != lendInformation.acceptedCollaterals.length");
        }
        assert(aggregatorContract != address(0));

        assert(lendInformation.principle != address(0));

        assert(lendInformation.acceptedCollaterals.length > 0);

        assert(lendInformation.maxLTVs.length == lendInformation.acceptedCollaterals.length);

        return true;
    }

The log on echidna

                                                     │ Workers: 0/4             │ Unique instructions: 3013                                        │ Chain ID: -                                                    │                                                     
                                                     │ Seed: 6835362162220902608│ Unique codehashes: 1                                             │ Fetched contracts: 0/1                                         │                                                     
                                                     │ Calls/s: 8359            │ Corpus size: 8 seqs                                              │ Fetched slots: 0/0                                             │                                                     
                                                     │ Gas/s: 5567698           │ New coverage: 2s ago                                             │                                                                │                                                     
                                                     │ Total calls: 50158/50000 │                                                                  │                                                                │                                                     
                                                     ├──────────────────────────┴────────────────────────────────────────────── Tests (16) ────────┴────────────────────────────────────────────────────────────────┤                                                     
                                                     │ assertion in checkInvalidInitializer(): FAILED! with ErrorRevert                                                                                            ^│                                                     
                                                     │                                                                                                                                                             █│                                                     
                                                     │ Call sequence:                                                                                                                                              █│                                                     
                                                     │ 1. DLOImplementationEchidnaTest.checkInvalidInitializer()                                                                                                   █│                                                     
                                                     │                                                                                                                                                             █│                                                     
                                                     │ Traces:                                                                                                                                                     █│                                                     
                                                     │ emit Log(value=«Aggregator contract  is address(0)»)                                                                                                        █│                                                     
                                                     │ (/Users/codertjay/GolandProjects/2024-11-debita-finance-v3-codertjay/Debita-V3-Contracts/contracts/echidna/EchidnaDebitaLendOffer-Implementation.sol:49)    █│                                                     
                                                     │ emit Log(valueprinciple is address(0)»)                                                                                                                   █│                                                     
                                                     │ (/Users/codertjay/GolandProjects/2024-11-debita-finance-v3-codertjay/Debita-V3-Contracts/contracts/echidna/EchidnaDebitaLendOffer-Implementation.sol:52)    █│                                                     
                                                     │ emit Log(valueacceptedCollaterals is zero in length»)                                                                                                     █│                                                     
                                                     │ (/Users/codertjay/GolandProjects/2024-11-debita-finance-v3-codertjay/Debita-V3-Contracts/contracts/echidna/EchidnaDebitaLendOffer-Implementation.sol:57)    █│                                                     
                                                     │ emit Log(valuelendInformation.maxLTVs.length != lendInformation.acceptedCollaterals.length»)                                                              █│                                                     
                                                     │ (/Users/codertjay/GolandProjects/2024-11-debita-finance-v3-codertjay/Debita-V3-Contracts/contracts/echidna/EchidnaDebitaLendOffer-Implementation.sol:61)     │                                                     
                                                     ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │                                                     
                                                     │ AssertionFailed(..): passing                                                                                                                                 │                                                     
                                                     ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │                                                     
                                                     │ assertion in acceptLendingOffer(uint256): passing                                                                                                            │                                                     
                                                     ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │                                                     
                                                     │ assertion in aggregatorIsZero(): passing                                                                                                                     │                                                     
                                                     ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │                                                     
                                                     │ assertion in initialize(address,bool,bool[],bool,uint256[],uint256,uint256,uint256,address,address,address[],address[],uint256[],address,uint256): passing   │                                                     
                                                     ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │                                                     
                                                     │ assertion in lendInformation(): passing                                                                                                                     v│                                                     
                                                     ├────────────────────────────────────────────────────────────────────────── Log (14) ──────────────────────────────────────────────────────────────────────────┤                                                     
                                                     │ [2024-11-16 11:28:54.04] [Worker 1] Test limit reached. Stopping.                                                                                           ^│                                                     
                                                     │ [2024-11-16 11:28:54.00] [Worker 2] Test limit reached. Stopping.                                                                                            │                                                     
                                                     │ [2024-11-16 11:28:53.99] [Worker 3] Test limit reached. Stopping.                                                                                            │                                                     
                                                     │ [2024-11-16 11:28:53.97] [Worker 0] Test limit reached. Stopping.                                                                                            │                                                     
                                                     │ [2024-11-16 11:28:51.53] [Worker 2] New coverage: 3013 instr, 1 contracts, 8 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:49.94] [Worker 3] New coverage: 3001 instr, 1 contracts, 7 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.86] [Worker 2] New coverage: 2889 instr, 1 contracts, 6 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.64] [Worker 3] New coverage: 2843 instr, 1 contracts, 5 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.50] [Worker 2] New coverage: 2388 instr, 1 contracts, 4 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.48] [Worker 0] New coverage: 2388 instr, 1 contracts, 3 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.48] [Worker 3] New coverage: 2388 instr, 1 contracts, 2 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.47] [Worker 1] New coverage: 2388 instr, 1 contracts, 1 seqs in corpus                                                                  │                                                     
                                                     │ [2024-11-16 11:28:48.38] [Worker 2] Test checkInvalidInitializer() falsified!                                                                                │                                                     
                                                     │ [2024-11-16 11:28:48.38] [Worker 0] Test checkInvalidInitializer() falsified!                                                                               v│                                                     
                                                     ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤                                                     
                                                     │                                                            Campaign complete, C-c or esc to exit                                                             │                                                     
                                                     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ```


### Mitigation

1. Add input validation in the initialize function:

```solidity
function initialize(
    address _aggregatorContract,
    bool _perpetual,
    bool[] memory _oraclesActivated,
    bool _lonelyLender,
    uint[] memory _maxLTVs,
    uint _apr,
    uint _maxDuration,
    uint _minDuration,
    address _owner,
    address _principle,
    address[] memory _acceptedCollaterals,
    address[] memory _oracleIDS_Collateral,
    uint[] memory _ratio,
    address _oracleID_Principle,
    uint _startedLendingAmount
) public initializer {
    // Add validation checks
    require(_aggregatorContract != address(0), "Invalid aggregator address");
    require(_principle != address(0), "Invalid principle token address");
    require(_acceptedCollaterals.length > 0, "Must accept at least one collateral");
    require(_maxLTVs.length == _acceptedCollaterals.length, "Array length mismatch");
    require(_ratio.length == _acceptedCollaterals.length, "Ratio array length mismatch");
    require(_oracleIDS_Collateral.length == _acceptedCollaterals.length, "Oracle array length mismatch");
    require(_oraclesActivated.length == _acceptedCollaterals.length, "Oracle activation array length mismatch");
    
    // Rest of the initialization code...
}
  1. Add logic to verify token contracts exist:
require(
    IERC20(_principle).totalSupply() >= 0,
    "Invalid principle token contract"
);

for (uint i = 0; i < _acceptedCollaterals.length; i++) {
    require(
        IERC20(_acceptedCollaterals[i]).totalSupply() >= 0,
        "Invalid collateral token contract"
    );
}