Summary
After analyzing the price calculation in Auction.sol, while there are rounding effects from integer division, the impact is minimal and follows standard DeFi practices.
Technical Analysis
function getPrice() public view returns (uint256) {
if (block.timestamp < state.startTime) return state.startingPrice;
if (block.timestamp >= state.endTime) return state.reservePrice;
return state.startingPrice - (
(state.startingPrice - state.reservePrice) *
(block.timestamp - state.startTime) /
(state.endTime - state.startTime)
);
}
Impact Analysis
Maximum Rounding Loss
startingPrice = 100 USDC
reservePrice = 90 USDC
duration = 100 seconds
Expected: 92.5 USDC
Actual: 92 USDC
Loss: 0.5 USDC (0.54% of price)
Cumulative Impact
Total Allocation = 1,000,000 ZENO
Maximum cumulative loss = 0.54% * Total Value
= 5,400 USDC for a 1M USDC auction
Why This Is Low Severity
Standard Practice
Integer arithmetic is standard in Solidity
Similar implementations in major protocols
Follows expected behavior
Minimal Impact
Built-in Bounds
if (block.timestamp < state.startTime) return state.startingPrice;
if (block.timestamp >= state.endTime) return state.reservePrice;
Recommended Improvement
contract Auction is IAuction, Ownable {
uint256 private constant PRECISION = 1e6;
function getPrice() public view returns (uint256) {
if (block.timestamp < state.startTime) return state.startingPrice;
if (block.timestamp >= state.endTime) return state.reservePrice;
uint256 timeElapsed = block.timestamp - state.startTime;
uint256 duration = state.endTime - state.startTime;
uint256 progress = (timeElapsed * PRECISION) / duration;
uint256 priceDiff = state.startingPrice - state.reservePrice;
return state.startingPrice - ((priceDiff * progress) / PRECISION);
}
}
Test Cases
contract AuctionPriceTest is Test {
function testPriceCalculation() public {
uint256 startTime = block.timestamp;
uint256 endTime = startTime + 100;
uint256 startPrice = 100e6;
uint256 reservePrice = 90e6;
Auction auction = new Auction(
address(zeno),
address(usdc),
address(business),
startTime,
endTime,
startPrice,
reservePrice,
1000e18,
address(this)
);
vm.warp(startTime + 50);
uint256 midPrice = auction.getPrice();
assertApproximatelyEqual(midPrice, 95e6, 1e4);
}
}