💀Examples Of Vulnerabilities To Do With Assuming 18 Decimals
Understanding the Examples: In the "Examples" section, we delve into practical instances of vulnerabilities tied to incorrect assumptions regarding the 18-decimal standard in ERC20 tokens. The examples provided are not theoretical but are drawn from authentic bug bounty reports and analyses from various coding arenas. These real-world cases shed light on the genuine risks and vulnerabilities developers and auditors may encounter due to the misunderstanding or misuse of the decimal property in ERC20 tokens.
By scrutinizing these actual occurrences of decimal-related vulnerabilities, you will gain a deeper, more concrete understanding of the potential risks and detrimental impacts associated with the incorrect handling of token decimals. Engaging with these real-life scenarios will not only enhance your awareness of the challenges and pitfalls but also significantly sharpen your skills in auditing and developing secure, robust smart contracts. This practical insight prepares you for the intricacies and nuances of ensuring smart contract security in the dynamic and ever-evolving landscape of blockchain technology.
Code4rena Bug Bountry Payout
At line 156 of the TwapOracle.sol
file, the code performs the following calculation:
This calculation method raises concerns due to the way it handles the decimal property of ERC20 tokens. Let’s break it down:
For an ERC20 token with 18 decimals, the calculation effectively becomes:
This calculation is problematic and counterintuitive, as it arbitrarily multiplies the sumUSD
by the number of decimals (which in this case is assumed to be 18), rather than accurately scaling the value based on the token's actual decimal count. This approach results in inaccurate and misleading values.
It seems the original intent behind this line of code might have been to scale sumUSD
appropriately based on the token's decimal count. The correct way to achieve this scaling is to introduce a scalingFactor
that aligns with the token's decimals, as demonstrated below:
With this adjustment, sumUSD
is accurately multiplied by the token's scaling factor, providing a correct and reliable result that reflects the token's true value, considering its specific decimal count.
This issue is marked with high severity due to the critical role the exchange rate plays, especially as it is utilized in a minting mechanism within the smart contract. Ensuring the accuracy and integrity of the oracle calculation is paramount, as it is a focal point of the smart contract audit. Inaccurate oracle calculations, stemming from incorrect decimal handling, can lead to significant errors and vulnerabilities in the smart contract’s operation, ultimately compromising its security and reliability. Thus, attentiveness to the proper handling of token decimals is crucial for preventing such high-severity issues.
Wrong token allocation computation for token decimals != 18 if floor price not reached
Vulnerability Details
The vulnerability arises within the LaunchEvent.createPair
function, particularly when the set floor price is not attained — identified by the condition floorPrice > wavaxReserve * 1e18 / tokenAllocated
. Under this circumstance, the number of tokens dispatched to the pool is adjusted downwards to align with the raised WAVAX at the designated floor price.
It's crucial to note that floorPrice
is expected to possess a precision of 18 decimals, as indicated by the comment annotation:
While the validation check floorPrice > (wavaxReserve * 1e18) / tokenAllocated
is correctly implemented, the subsequent computation for tokenAllocated
introduces a vulnerability due to its handling of token decimals:
This computation fails to produce the correct result when dealing with tokens that do not adhere to the 18-decimal standard.
Recommendation
To rectify this critical vulnerability, it is imperative to revise the tokenAllocated
computation within the LaunchEvent.createPair
function as follows:
Implementing this adjustment ensures that the allocated tokens are accurately computed, preventing potential allocation errors that could adversely impact the function's operation and the associated transactions on the platform. This precision is vital for ensuring the integrity and functionality of the smart contract, especially when handling tokens with varying decimal configurations.
makerPrice
assumes oracle price is always in 18 decimals
makerPrice
assumes oracle price is always in 18 decimalsVulnerability Details
The EIP1271Wallet._validateOrder
function is responsible for calculating a makerPrice
. This calculated value inherently possesses a decimal count equivalent to that of takerAmount
, which consistently stands at 18 decimals because the takerToken
is invariably WETH. The makerPrice
is then juxtaposed with the priceFloor
value returned from a Chainlink oracle. For the comparison to be coherent and accurate, the priceFloor
value must also be expressed in 18 decimals.
However, a significant risk is lurking here: while the old, now deprecated, Chainlink API used to return values in 18 decimals, there is no guarantee that future or updated APIs from Chainlink will maintain this format. Relying on the assumption of 18 decimals without verification or adjustment introduces a potential vulnerability and might lead to miscalculations and misinterpretations in the EIP1271Wallet._validateOrder
function.
Vulnerability Details
Tokens that possess a decimal count exceeding 18 introduce a serious vulnerability across various functions in the codebase. These functions are prone to reverting due to underflow issues when interacting with such tokens.
Below are highlighted sections of the codebase where the vulnerability is evident:
Each of these functions performs calculations where an 18-decimal standard is presumed. Consequently, tokens with decimal counts that deviate from this assumption, especially those with more than 18 decimals, are not supported and lead to calculation errors or function reverts.
Recommendation
To mitigate this vulnerability, it’s crucial to integrate checks and normalization procedures for token decimal counts within each vulnerable function:
Decimal Count Verification: Introduce conditional checks to ascertain the decimal count of the tokens involved in calculations. If a token’s decimal count exceeds 18, implement normalization procedures to align the decimal count with the expected 18-decimal format.
Normalization Procedure: For tokens with decimal counts surpassing 18, normalize their values by dividing them by the difference in their decimal count and the 18-decimal standard. This normalization should be conducted carefully to avoid loss of precision and to ensure that subsequent calculations within the functions remain accurate and reliable.
Implementing these recommendations will ensure compatibility and accurate calculations for all tokens, regardless of their decimal count, safeguarding the functions from underflows and enhancing the robustness and reliability of the smart contract.
Wrong price scale for GasOracle
GasOracle
The GasOracle
function engages with two distinct Chainlink oracles: one provides the gas price in ETH with a variable decimal count (GAS in ETH
), and the other offers the price of ETH in USD, also with a variable decimal count (USD per ETH
). To determine the gas price in USD, GasOracle
straightforwardly multiplies the raw values returned from these two oracles.
Nonetheless, this approach introduces a vulnerability due to the assumption embedded in the code. The calculation critically depends on the decimal counts of the values provided by the two oracles, which can indeed vary. Despite this variability, the existing code unilaterally assumes that the resulting value will adhere to an 18-decimal standard:
This assumption creates a misalignment between the expected and actual decimal count in the calculated values, generating potential inaccuracies in the gas price computed in USD. While a toWad
function is present in the codebase, which appears designed to handle scaling, it remains unused, leaving the decimal count issue unaddressed.
Impact
The failure to accurately scale the values from the oracles means the reported gas price in USD may not reflect reality, leading to substantial discrepancies. If the scale isn’t accurately aligned, the gas price can either be significantly inflated or underreported. Such misrepresentations can lead to financial inaccuracies and miscalculations during transactions, affecting users and potentially leading to loss of funds or other operational issues on the platform.
ERC20Rewards breaks when setting a different token
Vulnerability Details
The setRewards
function is designed with the capability to designate a different token for rewards. However, this flexibility inadvertently introduces a critical vulnerability: holders from a previous reward cycle who haven't claimed their rewards are subject to receiving their dues in a new token once it's set. This transition is problematic, particularly when the newly assigned token has a different value or operates with a different decimal structure than its predecessor.
Illustrative Example
Let’s walk through a scenario to illustrate the issue:
Assume in the first reward cycle, the reward token was DAI, which operates with 18 decimals. In this scenario, an individual who is entitled to claim rewards would receive DAI, or units of DAI given its decimal structure.
However, consider a situation where this individual decides not to claim the reward immediately. In the interim, a new reward cycle is initiated, this time with USDC (which operates with 6 decimals) as the reward token. Now, if the individual decides to claim their reward, they would receive their units, but this time in USDC. Given USDC’s decimal structure, this would translate to USDC, or a staggering one trillion USD, showcasing a drastic disparity and unintended windfall.
Impact
This vulnerability underscores a significant risk: the process of changing reward tokens is only seamless and error-free if the outgoing and incoming tokens share identical decimal structures and values. If there’s a mismatch in decimals or a disparity in value between the two tokens, users who delay or expedite their reward claims might experience substantial losses or undue gains, leading to fairness and distribution issues within the platform.
Last updated