Core Contracts

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

Incorrect Decimal Handling in Auction Contract Leading to Massive Overcharging

Summary

The Auction contract erroneously computes the USDC cost for purchasing ZENO tokens by multiplying the price by the amount without accounting for decimal precision. This results in a cost that is excessively high, potentially charging a buyer astronomically more USDC than intended.

Vulnerability Details

In the [buy](https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/zeno/Auction.sol#L87) function, the cost is calculated using:

function buy(uint256 amount) external whenActive {
uint256 price = getPrice();
uint256 cost = price * amount; // Incorrect: amount is in 1e18, price is in 1e6
require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
// ...
}
  • ZENO Decimals: 18 (1e18 units per token)

  • USDC Decimals: 6 (1e6 units per token)

  • Issue: The calculation price * amount multiplies a USDC price (1e6) by a ZENO amount (1e18), resulting in a cost value that is 1e12 times larger than intended.

Proof of Concept

Scenario Setup

  1. Auction Parameters:

    • Starting Price: 100 USDC (100e6 units)

    • Reserve Price: 50 USDC (50e6 units)

    • Current Price: 75 USDC (75e6 units)

  2. User Action:

    • User buys 1 ZENO token (1e18 units)

  3. Incorrect Calculation:

    cost = price * amount = 75e6 * 1e18 = 75e24 USDC units
    • Expected Cost: 75 USDC (75e6 units)

    • Actual Cost: 75e24 USDC units (75 followed by 24 zeros)

  4. Result:

    • The user is charged 75e18 USDC instead of 75 USDC, which is 1e12 times more than intended.

Impact

  • Users are overcharged by a factor of 1e12 (1,000,000,000,000x)

  • Funds are irreversibly transferred, making recovery impossible

Tools Used

Manual Review

  1. Numerical Simulation:

    # Vulnerability Proof
    price = 75e6 # 75 USDC in 1e6 units
    amount = 1e18 # 1 ZENO in 1e18 units
    cost = price * amount # 75e24 USDC units (75 followed by 24 zeros)
    print(f"Cost: {cost} USDC units") # Output: 75000000000000000000000000

Recommendations

Adjust the cost calculation to account for the difference in decimal precision:

function buy(uint256 amount) external whenActive {
uint256 price = getPrice();
uint256 cost = (price * amount) / 1e18; // Scale down by 1e18
require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
// ...
}
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!