You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ethers BigNumber转USD计算结果异常,请求排查原因

以太坊转USD计算BigNumber结果异常问题

问题描述

将以太坊价值转换为USD法定货币价值时,计算结果不符合预期,问题源于BigNumber的计算逻辑。

尝试代码

const one = parseUnits("1");
const price = parseUnits("0.1");
const _rate = "1563.48";
const rate = parseUnits(_rate, 2);
const usdPrice = price.lt(one) ? rate.mul(price) : rate.div(price);

结果对比

  • 预期结果:usdPrice = 156.348
  • 实际结果:usdPrice = 15634.8

问题原因

核心问题是parseUnits的小数位数不统一:

  • parseUnits("0.1")默认使用18位小数(对应以太坊wei单位),得到的是0.1 * 10^18的BigNumber
  • parseUnits(_rate, 2)使用2位小数,得到的是1563.48 * 10^2的BigNumber

直接相乘时,结果为0.1*1563.48 * 10^(18+2) = 156.348 * 10^20,若直接转换为可读数值时未做对应位数的除法,就会得到15634.8(相当于把156.348 *10^20除以了10^18,忽略了rate的2位小数)。

修复方案

方案1:统一小数位数计算

将rate的小数位数改为18位,和以太坊单位保持一致,计算后通过除以one(即1*10^18)得到正确的USD数值:

const one = parseUnits("1");
const price = parseUnits("0.1");
const _rate = "1563.48";
const rate = parseUnits(_rate, 18); // 统一为18位小数
const usdPriceBigNumber = price.lt(one) ? rate.mul(price).div(one) : rate.div(price);
// 转换为可读数值
const usdPrice = usdPriceBigNumber.div(parseUnits("1", 18)).toString();

方案2:计算后调整小数位数

直接计算后,除以10^(18+2)抵消两边的小数位放大:

const one = parseUnits("1");
const price = parseUnits("0.1");
const _rate = "1563.48";
const rate = parseUnits(_rate, 2);
const decimalAdjust = parseUnits("1", 20); // 10^(18+2)
const usdPriceBigNumber = price.lt(one) ? rate.mul(price).div(decimalAdjust) : rate.div(price).mul(parseUnits("1", 16));
// 转换为可读数值
const usdPrice = usdPriceBigNumber.toString();

方案3:先转换为实际数值再计算

先将price和rate转换为实际的ETH和USD/ETH数值,再进行计算,逻辑更直观:

const priceEth = parseUnits("0.1").div(parseUnits("1")); // 得到0.1的BigNumber表示
const rateUsdPerEth = parseUnits("1563.48", 2).div(parseUnits("1", 2)); // 得到1563.48的BigNumber表示
const usdPriceBigNumber = priceEth.mul(rateUsdPerEth);
// 转换为可读数值
const usdPrice = usdPriceBigNumber.toString();

内容的提问来源于stack exchange,提问作者Xavier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:50:21