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

NFT市场Solidity手续费计算异常与交易回退问题求解

问题根源
  • 你用ethers.utils.parseUnits()得到的auctionPrice是以wei为单位的BigNumber类型值,比如parseUnits("1", "ether")的实际值是1000000000000000000(1e18),本身已经是链上可识别的最小单位数值,不需要二次转换。
  • 你在计算完fee = (2.5 * auctionPrice) / 100后,又调用了一次parseUnits,相当于把已经是wei单位的手续费又乘以了1e18,直接导致数值放大了10^18倍,远超预期,最终触发合约执行失败。
修复方案

方案1:直接在JS侧正确计算手续费

注意BigNumber不能直接和小数运算,所以要调整计算逻辑,避免精度丢失:

const auctionPrice = ethers.utils.parseUnits("1", "ether");
// 2.5% 等价于 乘以25再除以1000,避免小数运算
const fee = auctionPrice.mul(25).div(1000);
// 直接用fee作为手续费值,不需要再parseUnits
const commissionValue = fee.toString();

console.log(commissionValue); // 1eth的话这里输出25000000000000000,也就是0.025eth,符合预期
console.log(ethers.utils.formatEther(commissionValue)); // 可以转成人类可读的eth数值看结果

const [_, userAddress] = await ethers.getSigners();
await market
  .connect(userAddress)
  .createMarketSale(nftContractAddress, 1, commissionValue, {
    value: auctionPrice,
  });

方案2:更安全的做法是把手续费计算逻辑放到链上合约里

前端只传交易价格,合约内部直接按比例扣手续费,避免前端篡改手续费数值:

// 合约内计算2.5%手续费的示例,避免浮点运算
uint256 fee = auctionPrice * 25 / 1000;
uint256 sellerReceive = auctionPrice - fee;
数值单位转换方法

如果你需要把链上返回的wei单位大数值转成人类可读的小数/整数,用ethers自带的工具即可:

  • wei转eth可读小数:ethers.utils.formatEther(大数值字符串),比如formatEther("25000000000000000")会返回0.025
  • 人类可读数字转wei:ethers.utils.parseUnits("0.025", "ether"),返回对应BigNumber类型的wei值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:06:04