Core Contracts

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

ZENO.sol, redeem() and redeemAll() does not take decimals to account and transfer usdc based on ZENO's decimals, letting anyone redeem more USDC than they are entitiled.

Summary

The ZENO contract lets users redeem USDC after it matures. The functions transfer USDC equilvalent to the amount of ZENO burned. However, since USDC has 6 decimals and ZENO has 18, (decimals is not overridden, the default decimals of openzeppelin's ERC20 is 18), for 1 ZENO burned, users will receive 1e18 of USDC, ~1000000000000 USDC.

Vulnerability Details

In redeem() and redeemAll(),

function redeem(uint amount) external nonReentrant {
....
_burn(msg.sender, amount);
USDC.safeTransfer(msg.sender, amount);
}
function redeemAll() external nonReentrant {
....
_burn(msg.sender, amount);
USDC.safeTransfer(msg.sender, amount);
}

Openzeppelin's ERC20,

function decimals() public view virtual returns (uint8) {
return 18;
}

Impact

This lets anyone gain 1e12 more USDC per 1 of ZENO, effectively draining the contract

Tools Used

Manual Review

Recommendations

Override the decimals() of ZENO and make it 6, or account for decimals before transferring USDC.

function redeemAll() external nonReentrant {
....
_burn(msg.sender, amount);
++ uint256 usdcAmount = (amount * USDC.decimals()) / decimals()
-- USDC.safeTransfer(msg.sender, amount);
++ USDC.safeTransfer(msg.sender, usdcAmount);
}
Updates

Lead Judging Commences

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