Core Contracts

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

Incorrect Refund Calculation in mint() Function on RAACNFT

Summary

The mint() function attempts to refund excess ERC-20 tokens when the user pays more than the required price. However, the refund logic does not verify if _amount sent by the user matches the expected price format, which can lead to over-refunding, under-refunding, or economic imbalances.

Since there are no ERC-20 decimal differences in this scenario, the risk is not related to decimal precision but instead to improper refund handling.

Vulnerability Details

  1. Refund Calculation Does Not Account for Edge Cases

    The mint() function includes this refund logic:

    if (_amount > price) {
    uint256 refundAmount = _amount - price;
    token.safeTransfer(msg.sender, refundAmount);
    }

    Potential Issues:

    • If _amount is only slightly greater than price, the contract still triggers an additional transfer for refunding.

    • This adds unnecessary gas costs and could be exploited through transaction spam.

    • If an external contract manipulates _amount, the refund calculation could be abused to drain small amounts of tokens repeatedly.

  2. Attack Scenario: Refund-Based Manipulation

    An attacker could intentionally send slightly more than the required amount, repeatedly triggering the refund logic and causing gas inefficiencies or exploiting small imbalances in rounding logic.

    Example:

    • Attacker sends 100.0000000001 tokens instead of exactly 100.0000000000 tokens.

    • The contract accepts the payment and processes the mint, but the refund logic is still triggered to send back the excess amount.

    • If the attacker performs this many times, they could cause excessive gas consumption and potential token rounding errors.

Impact

  • Every small overpayment triggers an extra transfer, increasing gas costs.

  • Attackers can intentionally overpay in tiny amounts, forcing repeated token transfers and causing inefficiencies.

  • If small excess payments accumulate, refund calculations may not match expected amounts, leading to unexpected token distribution imbalances.

PoC

const { expect } = require("chai");\
const { ethers } = require("hardhat");
describe("Refund Calculation Issue in RAACNFT", function () {
let raacNFT, token, owner, attacker;
beforeEach(async function () {
[owner, attacker] = await ethers.getSigners();
const ERC20 = await ethers.getContractFactory("ERC20Mock");
token = await ERC20.deploy("Test Token", "TTK", owner.address, ethers.utils.parseEther("10000"));
await token.deployed();
const RAACNFT = await ethers.getContractFactory("RAACNFT");
raacNFT = await RAACNFT.deploy(token.address, owner.address);
await raacNFT.deployed();
await token.connect(attacker).approve(raacNFT.address, ethers.utils.parseEther("100"));
});
it("should trigger unnecessary refunds on small overpayments", async function () {
const price = ethers.utils.parseEther("10");
for (let i = 0; i < 5; i++) {
let excessAmount = price.add(1); // Sending slightly more than required
await expect(raacNFT.connect(attacker).mint(i, excessAmount))
.to.emit(raacNFT, "NFTMinted")
.and.to.emit(token, "Transfer"); // Refund transaction also triggers
// Check attacker's balance after repeated minting
expect(await token.balanceOf(attacker.address)).to.be.closeTo(
ethers.utils.parseEther("9990"), // Should not be more than expected refund
ethers.utils.parseEther("0.0000000001") // Small rounding error tolerance
);
}
});
});

Tools Used

Manual Review, Hardhat

Recommendations

Introduce the minimum threshold for refunds

Modify the mint() function to only trigger refunds if the excess amount exceeds a certain threshold (e.g., 0.01 tokens).

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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