Core Contracts

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

totalZENORedeemed will always exceed the ZENO contract’s USDC balance

Summary

The invariant is that The ZENO contract's USDC balance must always be ≥ totalZENORedeemed. However this is broken.

Vulnerability Details

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);
}
function redeem(uint amount) external nonReentrant {
if (!isRedeemable()) {
revert BondNotRedeemable();
}
if (amount == 0) {
revert ZeroAmount();
}
uint256 totalAmount = balanceOf(msg.sender);
if (amount > totalAmount) {
revert InsufficientBalance();
}
totalZENORedeemed += amount;
_burn(msg.sender, amount);
USDC.safeTransfer(msg.sender, amount);
}

The Auction contract sends USDC to businessAddress during purchases, not to the ZENO contract.

The ZENO contract’s redeem function attempts to transfer USDC from its own balance to users, but it never receives USDC.

totalZENORedeemed will always exceed the ZENO contract’s USDC balance (which is permanently zero).

All redemption attempts will fail due to USDC.safeTransfer reverting.

Example Scenario:

  1. Auction mints 100 ZENO to Alice via mint()totalZENOMinted = 100.

    Auction sends 100 USDC to businessAddress (not ZENO contract).

    • After maturity, Alice calls redeem(100).

    • Contract checks balanceOf(Alice) = 100 → proceeds.

    • USDC.safeTransfer tries to send 100 USDC from ZENO’s balance (which is 0) → reverts.

Impact

All redemption attempts will fail due to USDC.safeTransfer reverting.

Tools Used

Manual Review

Recommendations

Deposit USDC into ZENO Contract: Modify the Auction’s buy function to send USDC to the ZENO contract (not businessAddress). This ensures the ZENO contract holds sufficient USDC for redemptions.

Updates

Lead Judging Commences

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