Boost _ Folks Finance 33665 - [Smart Contract - Critical] Collateral Inflation Exploit via Zero-Amou

Submitted on Thu Jul 25 2024 22:47:16 GMT-0400 (Atlantic Standard Time) by @A2Security for Boost | Folks Finance

Report ID: #33665

Report type: Smart Contract

Report severity: Critical

Target: https://testnet.snowtrace.io/address/0x2cAa1315bd676FbecABFC3195000c642f503f1C9

Impacts:

  • attacker can drain an pool

  • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Description

Brief/Intro

  • The folks-finance defi system contains a critical vulnerability in its collateral accounting mechanism. This flaw allows malicious actors to artificially inflate their collateral value by exploiting zero-amount deposits. The issue stems from the lack of proper deduplication in the collateral tracking system and a naive summation in the collateral calculation process. This vulnerability enables attackers to borrow amounts far exceeding their actual collateral and draining all liquidity from any pool in the system.

Vulnerability Details

  • The vulnerability exists in the collateral accounting mechanism, specifically in the interaction between LoanManagerLogic.sol and UserLoanLogic.sol. It allows an attacker to artificially inflate their collateral value through zero-amount deposits and drain any pool.

  1. Zero-amount deposits in SpokeToken.sol: The createLoanAndDeposit function allows users to deposit any amount, including zero amounts.

     function createLoanAndDeposit(
         Messages.MessageParams memory params,
         bytes32 accountId,
         bytes32 loanId,
         uint256 amount,
         uint16 loanTypeId,
         bytes32 loanName
     ) external payable nonReentrant {
         _doOperation(
             params,
             Messages.Action.CreateLoanAndDeposit,
             accountId,
             amount,
             abi.encodePacked(loanId, poolId, amount, loanTypeId, loanName)
         );
     }
  2. Collateral tracking in UserLoanLogic.sol: The increaseCollateral function adds the poolId to loan.colPools every time a deposit is made to that pool if the user balance of that pool is 0 , even for zero-amount deposits.

    function increaseCollateral(LoanManagerState.UserLoan storage loan, uint8 poolId, uint256 fAmount) external {
     if (loan.collaterals[poolId].balance == 0) loan.colPools.push(poolId);
     loan.collaterals[poolId].balance += fAmount;
    }
  3. Collateral calculation in UserLoanLogic.sol: The getLoanLiquidity function iterates over loan.colPools, summing up collateral values without deduplicating repeated poolIds.

     function getLoanLiquidity(
         LoanManagerState.UserLoan storage loan,
         mapping(uint8 => IHubPool) storage pools,
         mapping(uint8 => LoanManagerState.LoanPool) storage loanPools,
         IOracleManager oracleManager
     ) internal view returns (DataTypes.LoanLiquidityParams memory loanLiquidity) {
         // ... (other code)
         poolsLength = loan.colPools.length;
         for (uint8 i = 0; i < poolsLength; i++) {
             poolId = loan.colPools[i];
             balance = loan.collaterals[poolId].balance.toUnderlingAmount(
                 pools[poolId].getUpdatedDepositInterestIndex()
             );
             // ... (calculation code)
         }
         // ... (other code)
     }
  4. Borrow execution in LoanManagerLogic.sol: The executeBorrow function relies on isLoanOverCollateralized, which uses the inflated collateral value.

         function executeBorrow(/* ... (parameters)*/) external {
         // ... (other checks)
         if (!userLoan.isLoanOverCollateralized(pools, loanType.pools, oracleManager)) {
             revert UnderCollateralizedLoan(params.loanId);
         }
         // ... (borrow execution)
     }
  • The vulnerability allows an attacker to artificially inflate their collateral value by making multiple zero-amount deposits before a real deposit, enabling them to borrow disproportionately large amounts against their actual deposited collateral and drain any pool. This is possible due to the lack of proper deduplication in the colPools array and the naive summation in the getLoanLiquidity function.

Impact Details

The impact of this vulnerability is catastrophic for the lending platform:

  • Pool Drainage: Attackers can systematically drain liquidity from any pool in the system by exploiting the inflated collateral calculation.

  • Economic Model Collapse: The fundamental economic model of the platform is compromised, as risk assessment and collateralization ratios become meaningless.

  • Loss of User Funds: Legitimate users will lose access to their deposited funds as pools are drained by attacker.

  • Platform Failure: The vulnerability lead to a complete breakdown of the lending platform, rendering it non-functional.

Proof of concept

Proof of Concept:

  • here a poc shows how alice was able to borrow more then it's deposited amount , basically draining pool and steal bobs funds

  • We have added a proof of concept, in foundry that forks avalanche fugi and interacts with the deployed version of the protocol in testnet. To run the proof of concept please add the following files under tests. Please also make sure foundry is initialized in the project, and declare the custom remapping @forge-std

  1. First FIle: test/pocs/base_test.sol

  1. Second File (includes the poc): test/pocs/forktest.t.sol

  • this is the result if we execute the test with :

    forge test --mt test_poc_1 -vvv

Last updated

Was this helpful?