Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

Decimal Mismatch Between Price Calculation and Token Transfer Leading to Incorrect USDC Transfer in Auction Contract

Summary

The getPrice() function in the Auction.sol contract returns a price with 6 decimal places (scaled by 1e6), while the Zeno tokens minted and transferred are expected to have 18 decimal places. This results in a significant mismatch in the cost calculation when users purchase Zeno tokens, causing them to pay a much higher amount of USDC than intended. The issue arises because the price returned by getPrice() is not properly normalized to match the 18 decimal format of Zeno tokens, leading to a calculation that involves incorrect scaling.

Vulnerability Details

The getPrice() function returns a price with 6 decimals (1e6), as the startingPrice and Reserve Price are in USDC tokens format, but the token transfer and minting mechanisms in the contract assume the price should be in the same decimal format as Zeno tokens, which use 18 decimals.

  • When a user buys 1000e18 tokens (1000 Zeno tokens), the total cost is calculated by multiplying the price (which has 6 decimals) by the token amount (which has 18 decimals). This results in an inflated cost calculation, where the user is required to transfer an excessive amount of USDC, e.g., 1000e24

  • The mismatch between the price and the token decimal formats causes the transfer to use an incorrect amount of USDC.

    function getPrice() public view returns (uint256) {
    if (block.timestamp < state.startTime) return state.startingPrice;
    if (block.timestamp >= state.endTime) return state.reservePrice;
    return state.startingPrice - ((state.startingPrice - state.reservePrice)*(block.timestamp - state.startTime)/(state.endTime - state.startTime));
    }
    function buy(uint256 amount) external whenActive {
    require(amount <= state.totalRemaining, "Not enough ZENO remaining");
    uint256 price = getPrice();
    @> issue uint256 cost = price * amount;
    require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
    bidAmounts[msg.sender] += amount;
    state.totalRemaining -= amount;
    state.lastBidTime = block.timestamp;
    state.lastBidder = msg.sender;
    zeno.mint(msg.sender, amount);
    emit ZENOPurchased(msg.sender, amount, price);
    }

Impact

Incorrect USDC Transfer: The user ends up transferring a much higher amount of USDC than expected for the purchase of Zeno tokens, potentially resulting in financial loss or unintended behavior.

Possible Revert: due to insufficient balance of user.

Tools Used

Manual Code Review

Recommendations

Normalize Price Scaling, normalize the cost for buying ZENO in USDC format so user is not overcharged.

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Auction.sol's buy() function multiplies ZENO amount (18 decimals) by price (6 decimals) without normalization, causing users to pay 1 trillion times the intended USDC amount

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.