> For the complete documentation index, see [llms.txt](https://reports.immunefi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://reports.immunefi.com/folks-finance/boost-_-folks-finance-34030-smart-contract-low-incorrect-rounding-down-in-hubpoollogicupdatewithwith.md).

# Boost \_ Folks Finance 34030 - \[Smart Contract - Low] Incorrect rounding down in HubPoolLogicupdateWi

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

Report ID: #34030

Report type: Smart Contract

Report severity: Low

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

Impacts:

* Contract fails to deliver promised returns, but doesn't lose value
* Smart contract unable to operate due to lack of token funds

## Description

## Description

Users' deposit balance is stored in *fToken*\* amount. **fToken** is a type of interest-bearing token so its exchange rate back to underlying amount grows as interest index grows. Users who want to withdraw can specify whether to withdraw an exact underlying amount or withdraw with their **fToken** amount.

When users withdraw by specifying an underlying amount, the `toFAmount` function converts this amount back to fToken. The conversion formula utilized in `toFAmount` is as follows:

```solidity
File: /contracts/hub/logic/HubPoolLogic.sol
function updateWithWithdraw(
    HubPoolState.PoolData storage pool,
    uint256 amount,
    bool isFAmount
) external returns (DataTypes.WithdrawPoolParams memory withdrawPoolParams) {
    // can withdraw even if pool is depreciated
    // update interest indexes before the interest rates change
    pool.updateInterestIndexes();

    if (isFAmount) {
        withdrawPoolParams.fAmount = amount;
        withdrawPoolParams.underlingAmount = amount.toUnderlingAmount(pool.depositData.interestIndex);
    } else {
        withdrawPoolParams.underlingAmount = amount;
        withdrawPoolParams.fAmount = amount.toFAmount(pool.depositData.interestIndex); @<-- incorrect rounding down
    }

    pool.depositData.totalAmount -= withdrawPoolParams.underlingAmount;
    pool.updateInterestRates();
}

File: /contracts/hub/libraries/MathUtils.sol
function toFAmount(uint256 underlyingAmount, uint256 depositInterestIndexAtT) internal pure returns (uint256) {
    return underlyingAmount.mulDiv(ONE_18_DP, depositInterestIndexAtT);
}
```

We can clearly see that `toFAmount` rounds down the division result. This causes an issue when users withdraw small amounts, like 1 wei. The `fToken` amount may round down to zero, allowing users to withdraw 1 wei of underlying token without correctly reducing their `fToken` balance.

## Impact

Adversaries can continously withdraw 1 wei of underlying amount of token without losing `fToken` balance. Although the gas cost from transction would offset attacker's profit, it can potentially cause an accounting error in HubPool's `totalAmount`.

## Proof of concept

## Proof-of-Concept

A test in the secret gist demonstrates the following situation:

1. BOB deposits 1e6 USDC and in his loan.
2. BOB withdraws all in fUSDC amount, but left 1 wei of USDC in his loan.
3. BOB withdraws again in underling amount, specifying 1 wei.
4. BOB gets 1 wei of USDC but still keep his 1 wei of fUSDC in the loan.

### Steps

1. Run `forge init --no-commit --no-git --vscode`.
2. Create a new test file, `FolksWithdraw.t.sol` in `test` directory.
3. Put the test from secret gist in the file: <https://gist.github.com/nnez/ee5f1791aa5083286932bb3fd9c78e71>
4. Run `forge t --match-contract FolksWithdrawRoundingTest -vv`
5. Observe that BOB's usdc balance is up by 20 wei but he loses 0 amount of fUSDC in his loan.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://reports.immunefi.com/folks-finance/boost-_-folks-finance-34030-smart-contract-low-incorrect-rounding-down-in-hubpoollogicupdatewithwith.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
