Core Contracts

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

Users realise loss of funds the second that the the purchase `ZENO` tokens from `Auction`

Summary

Users realise loss of funds the second that the they purchase ZENO tokens from Auction

Vulnerability Details

This is due to the way that the exchange is made:

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

As describe in the docs:

It functions similarly to a zero-coupon bond, fully backed by USDC.

And as of description zero-coupon bond represents:

A zero-coupon bond is an investment in debt that does not pay interest but instead trades at a deep discount.

imagine the following scenario:

  1. user buys 1e6 ZENO tokens (can't do 1 because it is 18 decimals) with price == 10, which means he pays 10 USDC

  2. at the maturity date he exchanges back his 1e6 ZENO tokens for 1e6 USDC, meaning he is in 90% loss

This makes the Auction x ZENO mechanism practically unusable, since no user will just give out money like that

Impact

Auction x ZENO mechanism is unusable

Tools Used

Manual Review

Recommendations

change the price calculation like this:

require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
-- uint256 cost = price * amount;
++ uint256 cost = price * amount / state.startingPrice;
require(
usdc.transferFrom(msg.sender, businessAddress, cost),
"Transfer failed"
);

This way the scenario changes as it follows:
(StartingPrice == 100; price == 90)

  1. If user want to purchase 1e7 ZENO tokens, he will pay 9e6 USDC

  2. Then at the maturity date for his 1e7 ZENO tokens, he will be able to redeem 10 USDC

This is far more reasonable and make the Auction x ZENO system actually usable

Updates

Lead Judging Commences

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