import { time } from "@nomicfoundation/hardhat-network-helpers";
it("Incorrect decimal handling in `Auction::buy()`", async function () {
const currentTime = await time.latest()
const maturityDate = currentTime + 86400 * 365;
await zenoFactory.createZENOContract(usdcAddress, maturityDate);
const zeno1Address = await zenoFactory.getZENO(1);
const zeno = (await ethers.getContractAt("ZENO", zeno1Address));
const usdcDecimals = 6n;
const zenoDecimals = await zeno.decimals();
expect(zenoDecimals).to.equal(18);
auctionStartTime = currentTime + 1 * 3600;
auctionEndTime = auctionStartTime + 86400;
startingPrice = ethers.parseUnits("100", usdcDecimals);
reservePrice = ethers.parseUnits("10", usdcDecimals);
totalZENOAllocated = ethers.parseUnits("10", zenoDecimals);
totalZENORemaining = totalZENOAllocated;
await auctionFactory.createAuction(
zeno1Address,
usdcAddress,
businessAddress,
auctionStartTime,
auctionEndTime,
startingPrice,
reservePrice,
totalZENOAllocated
);
const auction1Address = await auctionFactory.getAuction(1);
const auction = (await ethers.getContractAt("Auction", auction1Address));
zenoFactory.transferZenoOwnership(1, auction1Address);
await usdc.mint(addr1.address, ethers.parseUnits("10000000000000000000000", 6));
await usdc.connect(addr1).approve(auction1Address, ethers.parseUnits("10000000000000000000000", 6));
await time.setNextBlockTimestamp(auctionStartTime + 1);
const amountToBuy = ethers.parseUnits("1", zenoDecimals);
const usdcBalanceBefore = await usdc.balanceOf(addr1.address);
await auction.connect(addr1).buy(amountToBuy);
const zenoBalanceAfter = await zeno.balanceOf(addr1.address);
expect(zenoBalanceAfter).to.equal(amountToBuy);
const cost = await auction.getPrice();
const expectedCost = (cost * amountToBuy) / ethers.parseUnits("1", zenoDecimals);
const actualInflatedCost = (cost * amountToBuy);
expect(expectedCost).to.equal(ethers.parseUnits("99.998959", usdcDecimals));
expect(actualInflatedCost).to.equal(ethers.parseUnits("99.998959", zenoDecimals + usdcDecimals));
const usdcBalanceAfter = await usdc.balanceOf(addr1.address);
expect(usdcBalanceAfter).to.not.equal(usdcBalanceBefore - expectedCost);
expect(usdcBalanceAfter).to.equal(usdcBalanceBefore - actualInflatedCost);
console.log("actualInflatedCost", actualInflatedCost);
expect(actualInflatedCost).to.equal(expectedCost * ethers.parseUnits("1", 18));
});
function buy(uint256 amount) external whenActive {
require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
// Divide by 1e18 to account for ZENO decimals
- uint256 cost = price * amount;
+ uint256 cost = (price * amount) / 1e18; // adjusted for ZENO decimals
require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
// ... rest of the function
}