Core Contracts

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

Decimal mismatch in `ZENO::redeem` and `ZENO::redeemAll` leading to excessive token withdrawal

Summary

The ZENO::redeem and ZENO::redeemAll functions do not account for the decimal difference between the ZENO token (18 decimals) and USDC (6 decimals). This results in incorrect calculations when transferring USDC, potentially leading to significant overpayment or underpayment during redemption.

Vulnerability Details

Problem description

  • The redeem and redeemAll functions transfer USDC in an amount equivalent to the burned ZENO balance.

  • The ZENO token uses 18 decimals, while USDC only has 6 decimals.

  • The functions do not scale the amount properly before transferring USDC, leading to incorrect value transfers.

  • Users may receive an excessive or insufficient amount of USDC compared to the intended redemption value.

Affected Code in ZENO.sol

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); // @audit-issue Incorrect scaling between 18-decimal ZENO and 6-decimal USDC
}

Code Reference: https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/zeno/ZENO.sol#L62

function redeemAll() external nonReentrant {
if (!isRedeemable()) {
revert BondNotRedeemable();
}
uint256 amount = balanceOf(msg.sender);
totalZENORedeemed += amount;
_burn(msg.sender, amount);
USDC.safeTransfer(msg.sender, amount); // @audit-issue Incorrect scaling between 18-decimal ZENO and 6-decimal USDC
}

Code Reference: https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/zeno/ZENO.sol#L73

Steps to reproduce

  1. A user holds 1 ZENO (1e18 units) and attempts to redeem it.

  2. The function transfers 1 USDC (1e6 units) instead of the correct scaled value (1e18 should convert to 1e6 USDC).

  3. The user receives an unintended overpayment or underpayment.

Impact

  • Incorrect fund distribution: Users may receive an incorrect amount of USDC when redeeming ZENO.

  • Financial loss: Either the protocol or users may suffer losses due to improper scaling.

Tools Used

Manual Review

Recommendations

**Implement proper decimal scaling before transferring USDC: **Adjust the transferred amount by scaling the ZENO amount down to match USDC’s 6 decimals, ensure consistency in all redemption-related functions.

uint256 usdcAmount = amount / 1e12; // Convert from 18 decimals to 6 decimals
USDC.safeTransfer(msg.sender, usdcAmount);

By implementing these changes, the protocol can prevent incorrect fund distributions and maintain accurate financial calculations.

Updates

Lead Judging Commences

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

Decimal precision mismatch between ZENO token (18 decimals) and USDC (6 decimals) not accounted for in redemption, causing calculation errors and incorrect payments

Support

FAQs

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