Core Contracts

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

Price Recalculation Vulnerability in ZENO Token Redemption Function

Summary

A vulnerability exists in the ZENO auction contract that allows users to redeem their ZENO tokens for a fixed amount of USDC, which does not account for the fluctuating price of ZENO tokens at the time of redemption. As a result, users may redeem their tokens at a value significantly lower than the price they originally paid, leading to potential financial loss.

Vulnerability Details

User wants to buy ZENOtokens with USDC he calls buy with amount of ZENO tokens he wants to buy

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);
}

It calculates how much USDC user should pay by calling getPrice() and returning the price. Current price of 1 ZENO per USDC depends from the timestamp. User pays (ex. 50 USDC) for 10 ZENO. Then he gets minted 10 ZENO to his address.
When timestamp passes endTime user can call redeem to get his USDC back for the ZENO. However in ZENO.SOLcontract when user calls redeem since he has 10 ZENO he can redeem only 10 ZENO and receive back 10 USDC. Those 40 USDC are lost. Bug happens because there is no calculation which gets the current price between ZENO and USDC.

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);
//@audit
USDC.safeTransfer(msg.sender, amount);
}

Impact

User receives less amount of USDC than he origianly had when buying ZENO.

Financial Loss: Users who redeem their ZENO tokens at a fixed value could face significant financial losses if the price of ZENO tokens has decreased since their purchase. This creates a potential mismatch between the value paid for the tokens and the value received upon redemption.

Tools Used

Manual Review

Recommendations

In redeem calculate current price of ZENO to USDC so user can receive the right amount of USDC

Example:

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);
uint256 price = getPrice();
uint256 usdcAmount = price * amount;
USDC.safeTransfer(msg.sender, usdcAmount);
}
Updates

Lead Judging Commences

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

ZENO.sol implements fixed 1:1 redemption with USDC regardless of auction purchase price, breaking zero-coupon bond economics and causing user funds to be permanently lost

Support

FAQs

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