Safely handle token decimal differences across EVM chains and bridged assets.
Copy the install command and let the AI configure it · recommended for beginners
Please install the "evm-token-decimals" skill from askskill: 1. Download https://raw.githubusercontent.com/affaan-m/ECC/main/skills/evm-token-decimals/SKILL.md 2. Save it as ~/.claude/skills/evm-token-decimals/SKILL.md 3. Reload skills and tell me it's ready
Design a safe token decimals handling strategy for an EVM DeFi bot: include runtime decimals lookup, caching by chainId + tokenAddress, handling bridged tokens with different decimals across chains, and provide a TypeScript example that normalizes raw on-chain amounts to 18-decimal precision plus a checklist of common pitfalls.
A practical multi-chain decimals handling strategy with caching rules, normalization code, and risk notes.
In my multi-chain portfolio dashboard, the same bridged USDC shows inconsistent balances and price conversions across chains. Help me create a debugging workflow: how to verify token decimals sources, detect stale cache or wrong mappings, distinguish native versus bridged tokens, and output a diagnostic checklist.
A systematic diagnostic workflow to pinpoint display issues caused by decimals, cache, or mapping errors.
Design a decimals validation mechanism for an on-chain analytics pipeline: the input includes token transfer events and token metadata from multiple EVM chains. Output validation rules to detect missing decimals, unexpected changes, and bridged-asset precision drift, plus alert conditions and pseudocode.
A precision validation and alerting plan for data pipelines that catches multi-chain token decimal issues early.
Silent decimal mismatches are one of the easiest ways to ship balances or USD values that are off by orders of magnitude without throwing an error.
Never assume stablecoins use the same decimals everywhere. Query decimals() at runtime, cache by (chain_id, token_address), and use decimal-safe math for value calculations.
from decimal import Decimal
from web3 import Web3
ERC20_ABI = [
{"name": "decimals", "type": "function", "inputs": [],
"outputs": [{"type": "uint8"}], "stateMutability": "view"},
{"name": "balanceOf", "type": "function",
"inputs": [{"name": "account", "type": "address"}],
"outputs": [{"type": "uint256"}], "stateMutability": "view"},
]
def get_token_balance(w3: Web3, token_address: str, wallet: str) -> Decimal:
contract = w3.eth.contract(
address=Web3.to_checksum_address(token_address),
abi=ERC20_ABI,
)
decimals = contract.functions.decimals().call()
raw = contract.functions.balanceOf(Web3.to_checksum_address(wallet)).call()
return Decimal(raw) / Decimal(10 ** decimals)
Do not hardcode 1_000_000 because a symbol usually has 6 decimals somewhere else.
from functools import lru_cache
@lru_cache(maxsize=512)
def get_decimals(chain_id: int, token_address: str) -> int:
w3 = get_web3_for_chain(chain_id)
contract = w3.eth.contract(
address=Web3.to_checksum_address(token_address),
abi=ERC20_ABI,
)
return contract.functions.decimals().call()
try:
decimals = contract.functions.decimals().call()
except Exception:
logging.warning(
"decimals() reverted on %s (chain %s), defaulting to 18",
token_address,
chain_id,
)
decimals = 18
Log the fallback and keep it visible. Old or non-standard tokens still exist.
interface IERC20Metadata {
function decimals() external view returns (uint8);
}
function normalizeToWad(address token, uint256 amount) internal view returns (uint256) {
uint8 d = IERC20Metadata(token).decimals();
if (d == 18) return amount;
if (d < 18) return amount * 10 ** (18 - d);
return amount / 10 ** (d - 18);
}
import { Contract, formatUnits } from 'ethers';
const ERC20_ABI = [
'function decimals() view returns (uint8)',
'function balanceOf(address) view returns (uint256)',
];
async function getBalance(provider: any, tokenAddress: string, wallet: string): Promise<string> {
const token = new Contract(tokenAddress, ERC20_ABI, provider);
const [decimals, raw] = await Promise.all([
token.decimals(),
token.balanceOf(wallet),
]);
return formatUnits(raw, decimals);
}
cast call <token_address> "decimals()(uint8)" --rpc-url <rpc>
decimals() at runtimeDecimal, BigInt, or equivalent exact math, not floatHandle returns, refunds, fraud checks, and warranty claim decisions efficiently.
Use Bun for runtime, bundling, testing, packages, and Node migration decisions.
Use the correct Ethereum Keccak-256 hashing in Node.js and TypeScript.
Apply Nuxt 4 patterns for SSR safety, performance, and data fetching.
Generate images, videos, and audio with one unified AI media workflow.
Design Quarkus 3 backend patterns for messaging, APIs, data, and async workflows.
Resolve EVM contract ABIs, inspect state, simulate calls, and prepare transactions.
Retrieve exact multi-chain protocol specs and canonical contract addresses with natural language.
Check EVM or Solana token rug risk with a clear 0-10 verdict.
Fetch and analyze ERC-20 metadata, balances, and allowances across chains.
Enable gasless payments and cross-chain transfers across multiple EVM networks.
Assess Base token exit cost, depeg risk, and liquidity fragility.