Boost _ Folks Finance 33816 - [Smart Contract - Critical] Attacker can get unlimited loan for some m

Submitted on Tue Jul 30 2024 02:49:29 GMT-0400 (Atlantic Standard Time) by @OxAnmol for Boost | Folks Finance

Report ID: #33816

Report type: Smart Contract

Report severity: Critical

Target: https://sepolia.etherscan.io/address/0x8Aac7fA5B2d0c7Ca4f1610bB43CF0d62A670Fa14

Impacts:

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

  • Protocol insolvency

Description

Brief/Intro

UserLoanLogic:getLoanLiquidity is used in the function isLoanOverCollateralized to calculate the user's available collateral value when they borrow or withdraw. The user's asset value depends on the length of the userLoan.colsPool[], which can be manipulated with minimal deposits. Because of this, collateral will be calculated incorrectly, leading to undesirable borrowing.

Vulnerability Details

There is no restriction on the minimal amount of collateral deposit for users. When a user deposits tokens, the fAmount is calculated based on the depositInterestIndex. If this index is greater than the user-provided amount * 1e18 (which is generally always the case), then the fAmount is rounded down to 0.

If the fAmount is zero, based on the logic of UserLoanLogic:increaseCollateral, the loanId (deposit token) is pushed to the userLoan.colsPool[].

Now, when a user’s fAmount is non-zero, it is also pushed to the colsPool[], and loan.collaterals[poolId].balance is incremented to a non-zero value.

When the user goes to borrow, their collateral value is calculated based on the balance stored in the mapping by looping through the userLoan.colsPool[]. This will inflate the value of the user's collaterals because colsPool[] may contain the same poolId multiple times, and for each poolId, the collateral value is calculated assuming they all have a non-zero amount stored in the loan.collaterals[poolId].balance mapping.

Because of this, a user can borrow a large amount and potentially drain the whole pool with this inflated collateral value for some minimal deposit.

https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/hub/logic/UserLoanLogic.sol#L283C4-L291C6

https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/hub/logic/UserLoanLogic.sol#L216C4-L275C6

Attack flow

  1. User deposit 1 wei or 0 (if the token doesn’t revert on 0 deposits) 10 times(can be any number).

  2. Because of toFAmount calculation the 1 wei is rounded to 0 fAmount.

  3. As the amount is 0 the poolId is pushed to userLoan.colsPool[] , this array will now contain [poolId…n] and loan.collaterals[poolId].balance is 0.

  4. Now the attacker deposit some actual amount let’s say 1e18(ETH). userLoan.colsPool[] now contains [poolId…n + poolId] and loan.collaterals[poolId].balance is updated to 1e18(1 ETH).

  5. user now and borrow 7.5 ETH with just 1 ETH deposit, if we only considered the 10 empty deposits.

  6. This happend because in getLoanLiquidity , protocol is assuming that colsPool[] only contains unique poolId .

As you can see that attacker have a power to drain almost all the available funds in the system with minimal collateral deposit.

Impact Details

This attack can lead to the loss of all the user funds and lead protocol to insolvency.

References

https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/hub/logic/UserLoanLogic.sol#L22

https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/hub/logic/UserLoanLogic.sol#L230C7-L244C10

Proof of concept

Here is a simple POC to demonstrate how the attack flow mentioned above works.

To run this POC, create new file inside test/hub and paste the code.

Last updated

Was this helpful?