Assessment reports>Palmy Finance>Medium findings>Reverting of the ,close, function due to the incorrect calculation in ,getHealthFactor
Category: Coding Mistakes

Reverting of the close function due to the incorrect calculation in getHealthFactor

Medium Severity
Medium Impact
High Likelihood

Description

Oasys Hub, the blockchain where Palmy Finance is deployed, only allows authorized users to deploy contracts. This imposes a limit to a user on calling multiple functions once unless one of the deployed contracts supports the specific series of calls.

The Leverager contract provides the utility functions that allow users to open or close the leveraged position on behalf of themselves. Opening a leveraged position works by repeatedly depositing an asset and borrowing the asset using the deposited asset as collateral. The other way around, closing a leveraged position, works by repeatedly repaying the debt and withdrawing the corresponding collateral.

The close function, which closes a leveraged position, involves calculating the withdrawable amount of the asset at each iteration. During this calculation, the close function calls the getHealthFactor function, which calculates the health factor after the user withdraws the given amount of the given asset. The source code of the getHealthFactor function is as follows:

function getHealthFactor(
	address account,
	address asset,
	uint256 withdrawAmount
) public view returns (uint256 healthFactor) {
    // ...
    uint256 reserveUnitPrice = priceOracleGetter.getAssetPrice(asset);
    // ...
	uint256 amountETH;
	amountETH = (withdrawAmount * reserveUnitPrice);
	totalCollateralAfter = (totalCollateral > amountETH)
		? totalCollateral - amountETH
		: 0;
    // ...
}

The amountETH variable is supposed to represent the total price of the asset to be withdrawn and is calculated by multiplying the withdrawAmount and the reserveUnitPrice. However, it is incorrect, because the the unit amount for the reserveUnitPrice is instead of .

If the decimal of the asset is not zero, the total collateral after the withdrawal will be underestimated due to this incorrect calculation. In most cases, this makes the function revert since this number is clamped to zero and used as a divisor.

Impact

A user will not be able to close a leveraged position through this contract. It is important to note that there are no other ways to close a leveraged position in a single transaction because a user is not allowed to deploy a contract that can perform this in a single transaction.

Users can manually close the position by interacting repeatedly with the lending pool contract. However, this process requires more time and exposes the user to the risk of being liquidated if they don't close the position promptly.

Recommendations

Consider fixing the calculation in the getHealthFactor function.

Remediation

This issue has been acknowledged by Familia Labs Ltd., and a fix was implemented in commit d97128aa.

Zellic © 2025Back to top ↑