我正在使用 ethers.js 进行智能合约测试,在执行交易后比较帐户的以太币余额时,我遇到了舍入错误的问题。具体来说,当我尝试测试拍卖系统的余额变化时,问题就出现了。
我正在使用 ethers.js v6。
在我的测试中,我正在计算费用金额,然后将以太币分配给卖方并退还给买方。然而,交易结束后,我在比较智能合约、买方和卖方的余额变化时遇到了 1 wei 的差异。这个问题似乎与计算中的舍入差异有关,我需要在测试时考虑到这一点。
逻辑:
function buy(uint index) external payable activeAuction(index) {
Auction storage auction = auctions[index];
require(block.timestamp < auction.endAt, "Auction has ended");
uint price = getPriceFor(index);
require(msg.value >= price, "Not enough money");
auction.stopped = true;
auction.finalPrice = price;
//refund
uint refund = msg.value - price;
if(refund > 0) {
payable(msg.sender).transfer(refund);
}
auction.seller.transfer(price - ((price * FEE)/100));
emit AuctionEnded(index, price, msg.sender);
}
测试方法:
it("Should allow to buy and refund", async () => {
const FEE = 10;
const oneEtherInWei = ethers.parseEther("1"); // 1 ETH = 1e18 wei
const twoEtherInWei = ethers.parseEther("2"); // 2 ETH = 2e18 wei
await expect(smartContract.connect(seller).createAuction(
oneEtherInWei,
FEE,
"test item",
60
));
const tx = await smartContract.connect(buyer).buy(0, { value: twoEtherInWei });
await tx.wait();
const feeAmount = (parseFloat(oneEtherInWei.toString()) * FEE) / 100;
console.log("feeAmount :", feeAmount);
const moneyForSeller = parseFloat(oneEtherInWei.toString()) - feeAmount;
console.log("moneyForSeller :", moneyForSeller);
const moneyLeftOnContract = parseFloat(oneEtherInWei.toString()) - moneyForSeller;
console.log("moneyLeftOnContract :", moneyLeftOnContract);
await expect(tx).to.changeEtherBalance(smartContract.target, moneyLeftOnContract.toString()) // Перевірка зміни балансу смарт-контракту
await expect(tx).to.changeEtherBalance(buyer.address, (parseFloat(twoEtherInWei) * -1).toString()) // Перевірка зміни балансу покупця
await expect(tx).to.changeEtherBalance(seller.address, moneyForSeller.toString()) // Перевірка зміни балансу продавця
const price = await smartContract.auctions(0).finalPrice;
expect(tx).to.emit(smartContract, "AuctionEnded")
.withArgs(0, price, buyer);
});
我会尝试在 BigNumber 中进行计算,而不是全部转换为浮点数。所以你没有四舍五入。
//const feeAmount = (parseFloat(oneEtherInWei.toString()) * FEE) / 100;
const feeAmount = oneEtherInWei.mul(FEE).div(100);
//const moneyForSeller = parseFloat(oneEtherInWei.toString()) - feeAmount;
const moneyForSeller = oneEtherInWei.sub(feeAmount);
//const moneyLeftOnContract = parseFloat(oneEtherInWei.toString()) - moneyForSeller;
const moneyLeftOnContract = oneEtherInWei.sub(moneyForSeller);