Core Contracts

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

Incorrect Cost Calculation in `Auction.buy()` Due to Decimal Mismatch Leading to Overpayment

Summary

In Auction contract, there is an incorrect cost calculation in the `buy()` function leads to an overpayment issue due to mismatched decimal precision between ZENO (18 decimals) and USDC (6 decimals). This results in users paying significantly more USDC than intended when purchasing ZENO tokens.

Vulnerability Details

In the `buy()` function, the cost of ZENO tokens is calculated as:

function buy(uint256 amount) external whenActive {
require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
@> 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);
}

• price is derived from getPrice(), which returns a value in USDC’s decimal precision (6 decimals).

• amount represents the ZENO tokens, which use 18 decimals.

• Multiplying a 6-decimal value (price) by an 18-decimal value (amount) results in a 24-decimal value.

• Since USDC only supports 6 decimals, this results in an overpayment by a factor of 1e12.

For example, if:

• price = 2 USDC (2 * 10^6)

• amount = 1 ZENO (1 * 10^18)

• cost = 2e6 * 1e18 = 2e24

This is 12 orders of magnitude higher than the correct amount.

Impact

• Users overpay to buy ZENO token, causing them to lose funds.

Tools Used

Manual Review

Recommendations

To fix this issue, scale the cost calculation properly by dividing by 1e18:

function buy(uint256 amount) external whenActive {
require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
- uint256 cost = price * amount;
+ uint256 cost = price * amount / 1e18;
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);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 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.

Give us feedback!