Skip to content

Commit

Permalink
Add max price range check in SealedBidTokenSale and update unit tests…
Browse files Browse the repository at this point in the history
… accordingly.
  • Loading branch information
ylv-io committed Feb 6, 2025
1 parent 36a5599 commit e69f4d2
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 28 deletions.
10 changes: 10 additions & 0 deletions src/apps/SealedBidTokenSale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ contract SealedBidTokenSale is Ownable, ReentrancyGuard {
error MerkleRootNotSet();
/// @notice Thrown when attempting to deposit less than MIN_DEPOSIT
error MinDeposit(uint256 amount);
/// @notice Thrown when new max price is out of range
error MaxPriceOutOfRange(uint256 amount);

/* ============ Events ============ */

Expand Down Expand Up @@ -179,6 +181,7 @@ contract SealedBidTokenSale is Ownable, ReentrancyGuard {
if (block.timestamp < startTime) revert SaleNotStarted(block.timestamp, startTime);
if (saleEnded) revert SaleAlreadyEnded(block.timestamp);
if (amount < MIN_DEPOSIT) revert MinDeposit(amount);
_checkMaxPrice(maxPrice);

// Update deposit accounting
deposits[msg.sender] += amount;
Expand Down Expand Up @@ -272,12 +275,19 @@ contract SealedBidTokenSale is Ownable, ReentrancyGuard {
function updateMaxPrice(uint256 newMaxPrice) external nonReentrant {
if (block.timestamp < startTime) revert SaleNotStarted(block.timestamp, startTime);
if (saleEnded) revert SaleAlreadyEnded(block.timestamp);
_checkMaxPrice(newMaxPrice);

uint256 oldPrice = maxPrices[msg.sender];
maxPrices[msg.sender] = newMaxPrice;
emit MaxPriceUpdated(msg.sender, oldPrice, newMaxPrice);
}

function _checkMaxPrice(uint256 newMaxPrice) internal pure {
if (newMaxPrice < 10 * 1e6 || newMaxPrice > 30 * 1e6) {
revert MaxPriceOutOfRange(newMaxPrice);

Check warning on line 287 in src/apps/SealedBidTokenSale.sol

View check run for this annotation

Codecov / codecov/patch

src/apps/SealedBidTokenSale.sol#L287

Added line #L287 was not covered by tests
}
}

/* ============ Admin Functions ============ */

/**
Expand Down
46 changes: 18 additions & 28 deletions test/unit/apps/SealedBidTokenSale.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ contract SealedBidTokenSaleTest is SharedSetup {
bytes32[] public proof;
uint256 public saleTokenAllocation = 1000 * 1e18;
uint256 public usdcAllocation = 1000 * 1e6;
uint256 public maxPrice = 1000 * 1e6;
uint256 public maxPrice = 10 * 1e6;

function setUp() public override {
super.setUp();
Expand Down Expand Up @@ -1054,8 +1054,8 @@ contract SealedBidTokenSaleTest is SharedSetup {
// Should work during sale
vm.warp(startTime + 1);
vm.prank(alice);
sale.updateMaxPrice(1e6);
assertEq(sale.maxPrices(alice), 1e6);
sale.updateMaxPrice(10e6);
assertEq(sale.maxPrices(alice), 10e6);

// Should fail after sale ends
vm.prank(admin);
Expand All @@ -1073,19 +1073,19 @@ contract SealedBidTokenSaleTest is SharedSetup {
assertEq(sale.maxPrices(alice), 0);

// First update
uint256 firstPrice = 1e6;
uint256 firstPrice = 10e6;
vm.prank(alice);
sale.updateMaxPrice(firstPrice);
assertEq(sale.maxPrices(alice), firstPrice);

// Update to higher price
uint256 higherPrice = 2e6;
uint256 higherPrice = 20e6;
vm.prank(alice);
sale.updateMaxPrice(higherPrice);
assertEq(sale.maxPrices(alice), higherPrice);

// Update to lower price
uint256 lowerPrice = 5e5;
uint256 lowerPrice = 15e6;
vm.prank(alice);
sale.updateMaxPrice(lowerPrice);
assertEq(sale.maxPrices(alice), lowerPrice);
Expand All @@ -1094,47 +1094,37 @@ contract SealedBidTokenSaleTest is SharedSetup {
vm.prank(alice);
sale.updateMaxPrice(lowerPrice);
assertEq(sale.maxPrices(alice), lowerPrice);

// Update to zero
vm.prank(alice);
sale.updateMaxPrice(0);
assertEq(sale.maxPrices(alice), 0);

// Update to max uint256
vm.prank(alice);
sale.updateMaxPrice(type(uint256).max);
assertEq(sale.maxPrices(alice), type(uint256).max);
}

function testUpdateMaxPrice_MultipleUsersIndependently() public {
vm.warp(startTime + 1);

// Update prices for different users
vm.prank(alice);
sale.updateMaxPrice(1e6);
assertEq(sale.maxPrices(alice), 1e6);
sale.updateMaxPrice(10e6);
assertEq(sale.maxPrices(alice), 10e6);

vm.prank(bob);
sale.updateMaxPrice(2e6);
assertEq(sale.maxPrices(bob), 2e6);
sale.updateMaxPrice(20e6);
assertEq(sale.maxPrices(bob), 20e6);

// Verify changes don't affect other users
assertEq(sale.maxPrices(alice), 1e6);
assertEq(sale.maxPrices(bob), 2e6);
assertEq(sale.maxPrices(alice), 10e6);
assertEq(sale.maxPrices(bob), 20e6);

// Update alice's price again
vm.prank(alice);
sale.updateMaxPrice(3e6);
assertEq(sale.maxPrices(alice), 3e6);
assertEq(sale.maxPrices(bob), 2e6);
sale.updateMaxPrice(30e6);
assertEq(sale.maxPrices(alice), 30e6);
assertEq(sale.maxPrices(bob), 20e6);
}

function testUpdateMaxPrice_WithDeposit() public {
vm.warp(startTime + 1);

// Setup initial deposit with maxPrice
uint256 depositAmount = 1000 * 1e6;
uint256 initialMaxPrice = 2e6;
uint256 initialMaxPrice = 10 * 1e6;

usdc.mint(alice, depositAmount);
vm.prank(alice);
Expand All @@ -1145,7 +1135,7 @@ contract SealedBidTokenSaleTest is SharedSetup {
assertEq(sale.maxPrices(alice), initialMaxPrice);

// Update maxPrice after deposit
uint256 newMaxPrice = 3e6;
uint256 newMaxPrice = 30 * 1e6;
vm.prank(alice);
sale.updateMaxPrice(newMaxPrice);
assertEq(sale.maxPrices(alice), newMaxPrice);
Expand All @@ -1158,7 +1148,7 @@ contract SealedBidTokenSaleTest is SharedSetup {
vm.warp(startTime + 1);

uint256 oldPrice = 0; // Initial price
uint256 newPrice = 1e6;
uint256 newPrice = 10e6;

vm.expectEmit(true, false, false, true);
emit SealedBidTokenSale.MaxPriceUpdated(alice, oldPrice, newPrice);
Expand Down

0 comments on commit e69f4d2

Please sign in to comment.