Core Contracts

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

ZENO mint amount in `Auction::buy` does not account for the price, leading to USDC loss when burning

Details

The minting and burning mechanism, as outlined in the docs is designed to allow users to reclaim their USDC when burning ZENO. However, in Auction::buy, the USDC amount transferred is calculated as price * amount, whereas the ZENO minted does not factor in the price. As a result, users cannot fully recover their USDC since ZENO::redeem also fails to account for the price.

POC

import {Test, console} from "forge-std/Test.sol";
import {ZENO} from "../contracts/zeno/ZENO.sol";
import {Auction} from "../contracts/zeno/Auction.sol";
import {MockUSDC} from "../contracts/mocks/core/tokens/MockUSDC.sol";
contract POC is Test {
ZENO zeno;
Auction auction;
MockUSDC usdc;
address owner = makeAddr("owner");
address user = makeAddr("user");
function setUp() public {
vm.startPrank(owner);
usdc = new MockUSDC(1 ether);
zeno = new ZENO(address (usdc), 3 weeks, "ZENO", "zeno", owner);
auction = new Auction(address(zeno), address(usdc), address(zeno), 1 days, 54 weeks, 1e6, 1e5,20 ether,owner);
usdc.mint(user, 100 ether);
zeno.transferOwnership(address(auction));
vm.stopPrank();
}
function test_POC() public {
uint256 userUsdcStartingBalance = usdc.balanceOf(user);
vm.warp(2 days);
vm.startPrank(user);
usdc.approve(address(auction), userUsdcStartingBalance);
auction.buy(1e14);
vm.warp(block.timestamp + 3 weeks);
zeno.redeemAll();
vm.stopPrank();
uint256 userUsdcClosingBalance = usdc.balanceOf(user);
assert(userUsdcClosingBalance < userUsdcStartingBalance);
}
}

Run forge test --mt test_POC -vvv the userUsdcClosingBalance is less than userUsdcStartingBalance to prove that upon burning users end up with lesser USDC.

Impact

Loss od USDC

Tool Used

Manual Review

Recommendation

function buy(uint256 amount) external whenActive {
- state.totalRemaining -= amount;
- zeno.mint(msg.sender, amount);
+ state.totalRemaining -= cost;
+ zeno.mint(msg.sender, cost);
}
Updates

Lead Judging Commences

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

Give us feedback!