代币锚定USD定价但以ETH购买的合约计算逻辑问题排查
代码错误分析及修正方案
核心错误点
- 父类方法返回值丢弃:你调用了
super._getTokenAmount(weiAmount)但完全没有使用其返回值,若父类该方法包含核心兑换逻辑会直接导致功能异常,如无特殊需求可以直接删除该行。 - 提前做除法导致精度严重损失:Solidity的整数运算默认向零截断,你第一行就执行
weiAmount / (10 * 10 ** 10),直接丢弃了weiAmount的后11位数值,小数部分完全损失,兑换金额越小误差越大。 - 汇率单位逻辑错误:以太坊上通用的ETH/USD预言机喂价(比如Chainlink)返回值为8位小数,含义是
1 ETH = (currentPrice / 1e8) USD,你现有代码的汇率计算逻辑完全颠倒,导致换算出的USD金额完全不符合预期。 - 运算顺序错误:整数运算必须遵循先乘后除的原则避免提前截断,你现有代码多次先除后乘,叠加后精度损失会被放大。
正确实现代码
function _getTokenAmount(uint weiAmount) internal override view returns(uint256) { int currentPrice = priceFeed.getLatestPrice(); require(currentPrice > 0, "Invalid price feed"); // 以下默认代币小数位为18位,是行业通用配置 // 计算公式对齐所有单位后先乘后除,避免精度损失 uint256 tokenAmount = weiAmount * uint256(currentPrice) * 25 / 1e8; // 若你的代币小数位为0,将上面一行替换为: // uint256 tokenAmount = weiAmount * uint256(currentPrice) * 25 / 1e26; return tokenAmount; }
验证示例
假设ETH价格为2000 USD,预言机返回的currentPrice = 2000 * 1e8:
用户支付1 ETH(即weiAmount = 1e18),按上述代码计算可得代币数量为1e18 * 2000e8 * 25 /1e8 = 50000e18,对应50000枚代币,完全符合1ETH=2000USD、1USD兑换25枚代币的预期逻辑。
内容的提问来源于stack exchange,提问作者LMan
相关产品推荐
相关产品推荐

