Precision errors often occur when dealing with tokens that have decimal points, especially when tokens with varying decimal standards (e.g., 6, 8, or 18 decimals) interact within the same system.
A mismatch in decimal handling can lead to incorrect calculations, resulting in inaccurate token transfers or balances.
Game
The transferAmount function assumes the token has 18 decimals, can you identify how this assumption could lead to a significant error in token transfers?
// SPDX-License-Identifier: MIT// Open me in VSCode and really think before opening the hints!// Add @audit tags wherever suspicious// Go to the solidity docs to complete missing knowledge of what's happening here// Solve by drafting a fix!pragmasolidity ^0.8.0;interface IERC20 {functiontransfer(address recipient,uint256 amount) externalreturns (bool);functionbalanceOf(address account) externalviewreturns (uint256);functiondecimals() externalviewreturns (uint8);}contract TokenDecimalsGame { IERC20 public token;constructor(address_token) { token =IERC20(_token); }functiontransferAmount(address recipient,uint256 amount) public {uint256 tokenAmount = amount *10**18;require(token.transfer(recipient, tokenAmount),"Transfer failed"); }}
ERC-20 tokens can have varying decimal places, often indicated by decimals(). If the contract assumes a specific decimal (e.g., 18), what might happen if the token has only 6 or 8 decimals?
Consider how amount * 10**18 would differ depending on the actual decimals of the token
Precision errors often arise when calculations assume a specific unit. In transferAmount, think about how the calculation could go wrong if the token's decimal setting differs from the assumed 18.
How could you dynamically adjust the transfer amount to match the token's decimals?
functiontransferAmount(address recipient,uint256 amount) public {uint8 decimals = token.decimals(); // Fix: Get the token's actual decimalsuint256 tokenAmount = amount *10**decimals;require(token.transfer(recipient, tokenAmount),"Transfer failed");}