Core Contracts

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

USDC may activate fees in the future, which will break accounting when people will try to redeem ZENO

Summary

USDC may activate fees in the future, which will break accounting, and cause issue when people will try to redeem ZENO.

Vulnerability details

USDC has a fee switch that could be activated in the future.
If this is the case, the amount of USDC received by Auction will not be the same as registered by the ZENO contract, causing funds to be stuck in the contract, and some users not able to withdraw their fair share.

E.g, if fee are 10% (for simplicity purpose), and users buy 100 ZENO, only 90 USDC will be received by the contract.
Now let's say 10 users do the same, they will hold 1000 ZENO, but the contract will hold 900 USDC.
If 9 users calls redeemAll(), they will withdraw the entire 900 USDC from the contract, and the tenth user will not be able to redeem its ZENO.

Proof of Concept

The amount minted is equal to the amount entered by the user, which does not factor possible fees:

File: contracts/zeno/Auction.sol
84: function buy(uint256 amount) external whenActive {
85: require(amount <= state.totalRemaining, "Not enough ZENO remaining");
86: uint256 price = getPrice();
87: uint256 cost = price * amount;
88: require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
89:
90: bidAmounts[msg.sender] += amount;
91: state.totalRemaining -= amount;
92: state.lastBidTime = block.timestamp;
93: state.lastBidder = msg.sender;
94:
95: zeno.mint(msg.sender, amount);
96: emit ZENOPurchased(msg.sender, amount, price);
97: }

When redeeming, the users will redeem more than the vault has received from them in term of USDC:

File: contracts/zeno/ZENO.sol
65: function redeemAll() external nonReentrant {
66: if (!isRedeemable()) {
67: revert BondNotRedeemable();
68: }
69:
70: uint256 amount = balanceOf(msg.sender);
71: totalZENORedeemed += amount;
72: _burn(msg.sender, amount);
73: USDC.safeTransfer(msg.sender, amount);
74: }

Recommended Mitigation Steps

Measure the real amount received by the contract using a USDCBalanceAfter - USDCbalanceBefore logic, and mint that value of ZENO to the user.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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