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
相关产品推荐
相关产品推荐

