The redeemAll function in the ZENO contract enforces a fixed 1:1 redemption ratio between ZENO and USDC, while Auction:buy() allows purchases at a variable price determined by getPrice(). Due to lack of proper scaling, users may pay significantly more USDC than they can redeem, resulting in substantial financial losses.
startingPrice & reservePrice Picks to avoid Rounding Error in getPrice()Found in contracts/zeno/Auction.sol at Line 76
The getPrice() function calculates the price of ZENO dynamically over time.
If (state.startingPrice - state.reservePrice) does not have enough precision, division by (state.endTime - state.startTime) can result in rounding errors.
Example: If the auction duration is 1 day (86400 seconds), then state.startingPrice - state.reservePrice must be at least 86400 (5 to 6 decimal places) to avoid loss of granularity.
buy() and redeemAll()buy()Found in contracts/zeno/Auction.sol at Line 87
The cost calculation is based on getPrice(), which must account for precision.
Given a 1-day auction duration, price should have at least 6 decimal places to ensure that users are charged the correct amount.
redeemAll()Found in contracts/zeno/ZENO.sol at Line 73
The redeemAll function forces a 1:1 redemption ratio between ZENO and USDC.
Severity: High
Users suffer a significant loss of funds due to the mismatch in price calculation vs. redemption ratio.
Example Attack Scenario:
Suppose the auction lasts 1 day (86400 seconds) , startingPrice & reservePrice must be at least 1e6.
Alice buys 1 wei ZENO at the end of the auction, paying 1e6 USDC.
On redemption, Alice receives only 1 wei USDC (instead of 1e6 USDC) due to the fixed 1:1 redemption ratio.
Alice loses 99.99% of her funds.
Manual review
Adjust the redeemAll function to properly scale the redemption ratio based on the auction price.
Modify cost calculation in buy() to account for decimal precision of getPrice, ensuring USDC:ZENO remains within an acceptable range (e.g., 1.xx:1 where xx represents protocol fees).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.