Skip to content

Latest commit

 

History

History
55 lines (31 loc) · 2.72 KB

085.md

File metadata and controls

55 lines (31 loc) · 2.72 KB

Formal Pecan Mongoose

Medium

Incorrect handling of decimals during conversions leading to errors

Summary

The functions ethToToken, ethToTokenRoundUp, tokenToEth, and tokenToEthRoundUp are intended to perform conversions between ETH and tokens, taking into account the token's decimals. However, the way the code adjusts for token decimals is incorrect, leading to inaccurate calculations.

Root Cause

https://github.com/sherlock-audit/2024-12-numa-audit/blob/main/Numa/contracts/libraries/OracleUtils.sol#L50C5-L98C60

    tokenAmount = tokenAmount * 10 ** (18 - _decimals);

The functions ethToToken, ethToTokenRoundUp, tokenToEth, and tokenToEthRoundUp are intended to perform conversions between ETH and tokens, taking into account the token's decimals. However, the way the code adjusts for token decimals is incorrect, leading to inaccurate calculations.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

https://github.com/sherlock-audit/2024-12-numa-audit/blob/main/Numa/contracts/libraries/OracleUtils.sol#L50C5-L98C60

// At the end of the ethToToken functions tokenAmount = tokenAmount * 10 ** (18 - _decimals);

// At the end of the tokenToEth functions EthValue = EthValue * 10 ** (18 - _decimals);

The functions attempt to adjust the calculated tokenAmount or EthValue by multiplying it with 10 ** (18 - _decimals). This adjustment is meant to account for the difference between the token's decimals and the standard 18 decimals used for ETH. However, this approach is flawed for several reasons.

Depending on whether the token's decimals are less than or greater than 18, you should either multiply or divide to adjust the amount correctly. Multiplying by 10 ** (18 - _decimals) when _decimals is less than 18 will massively scale up the amount, which is incorrect.

Impact

Users will receive incorrect amounts when converting between ETH and tokens, leading to potential financial losses or contract malfunctions. While some functions may return correct results for tokens with 18 decimals, they fail for tokens with different decimals.

Let's consider a token with 6 decimals (e.g., USDC), and we want to convert 1 ETH to USDC using the ethToToken function. The correct amount of USDC should be calculated based on the price feed and adjusted for the 6 decimals.

// After computing tokenAmount based on price feed tokenAmount = tokenAmount * 10 ** (18 - 6); // tokenAmount * 10^12 This incorrectly scales up the token amount by a factor of 1,000,000,000,000 (10^12), which is not appropriate for adjusting from 18 to 6 decimals.

PoC

No response

Mitigation

Adjust the tokenAmount and EthValue by dividing or multiplying based on the relation between the token's decimals and 18.