Skip to content

Commit

Permalink
test(billboard): add more tests for withdraw bids
Browse files Browse the repository at this point in the history
  • Loading branch information
robertu7 committed Jul 3, 2024
1 parent b0aae9c commit db48341
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 183 deletions.
41 changes: 23 additions & 18 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,37 @@ ACLManagerTest:testRoles() (gas: 15393)
ACLManagerTest:testTransferRole() (gas: 21528)
BillboardTest:testAddToWhitelist() (gas: 252168)
BillboardTest:testApproveAndTransfer() (gas: 252840)
BillboardTest:testCannotAddToWhitelistByAttacker() (gas: 225830)
BillboardTest:testCannotApproveByAttacker() (gas: 221688)
BillboardTest:testCannotClearAuctionIfAuctionNotEnded() (gas: 247623)
BillboardTest:testCannotClearAuctionIfNoBid() (gas: 255406)
BillboardTest:testCannotPlaceBidByAttacker() (gas: 459863)
BillboardTest:testCannotPlaceBidIfAuctionEnded() (gas: 270366)
BillboardTest:testCannotAddToWhitelistByAttacker() (gas: 225852)
BillboardTest:testCannotApproveByAttacker() (gas: 221710)
BillboardTest:testCannotClearAuctionIfAuctionNotEnded() (gas: 247677)
BillboardTest:testCannotClearAuctionIfNoBid() (gas: 255428)
BillboardTest:testCannotPlaceBidByAttacker() (gas: 459880)
BillboardTest:testCannotPlaceBidIfAuctionEnded() (gas: 270378)
BillboardTest:testCannotRemoveToWhitelistByAttacker() (gas: 225871)
BillboardTest:testCannotSafeTransferByAttacker() (gas: 218868)
BillboardTest:testCannotSetBoardByAttacker() (gas: 226929)
BillboardTest:testCannotSafeTransferByAttacker() (gas: 218890)
BillboardTest:testCannotSetBoardByAttacker() (gas: 226951)
BillboardTest:testCannotSetBoardByOwner() (gas: 359191)
BillboardTest:testCannotTransferByOperator() (gas: 224110)
BillboardTest:testCannotTransferToZeroAddress() (gas: 219554)
BillboardTest:testCannotTransferToZeroAddress() (gas: 219576)
BillboardTest:testCannotUpgradeRegistryByAttacker() (gas: 9038)
BillboardTest:testClearAuction(uint96) (runs: 256, μ: 712150, ~: 712150)
BillboardTest:testCannotWithdrawBidIfAuctionNotEndedOrCleared(uint96) (runs: 256, μ: 614753, ~: 614753)
BillboardTest:testCannotWithdrawBidIfNotFound(uint96) (runs: 256, μ: 730039, ~: 730039)
BillboardTest:testCannotWithdrawBidIfWon(uint96) (runs: 256, μ: 982286, ~: 982286)
BillboardTest:testCannotWithdrawBidTwice(uint96) (runs: 256, μ: 1065867, ~: 1065867)
BillboardTest:testClearAuction(uint96) (runs: 256, μ: 712172, ~: 712172)
BillboardTest:testClearAuctions() (gas: 1278587)
BillboardTest:testGetBids(uint8,uint8,uint8) (runs: 256, μ: 4938705, ~: 2145225)
BillboardTest:testGetTokenURI() (gas: 388777)
BillboardTest:testGetBids(uint8,uint8,uint8) (runs: 256, μ: 4721233, ~: 1988178)
BillboardTest:testGetTokenURI() (gas: 388799)
BillboardTest:testMintBoard() (gas: 417504)
BillboardTest:testPlaceBid(uint96) (runs: 256, μ: 798108, ~: 800441)
BillboardTest:testPlaceBidWithHigherPrice(uint96) (runs: 256, μ: 975862, ~: 975867)
BillboardTest:testPlaceBidWithSamePrices(uint96) (runs: 256, μ: 865951, ~: 869450)
BillboardTest:testPlaceBidZeroPrice() (gas: 416622)
BillboardTest:testRemoveToWhitelist() (gas: 238830)
BillboardTest:testPlaceBid(uint96) (runs: 256, μ: 798110, ~: 800443)
BillboardTest:testPlaceBidWithHigherPrice(uint96) (runs: 256, μ: 975879, ~: 975884)
BillboardTest:testPlaceBidWithSamePrices(uint96) (runs: 256, μ: 865740, ~: 869472)
BillboardTest:testPlaceBidZeroPrice() (gas: 416644)
BillboardTest:testRemoveToWhitelist() (gas: 238874)
BillboardTest:testSafeTransferByOperator() (gas: 232599)
BillboardTest:testSetBoardByCreator() (gas: 339600)
BillboardTest:testUpgradeRegistry() (gas: 3326886)
BillboardTest:testUpgradeRegistry() (gas: 3326686)
BillboardTest:testWithdrawBid(uint96) (runs: 256, μ: 1054698, ~: 1054698)
CurationTest:testCannotCurateERC20CurateZeroAmount() (gas: 12194)
CurationTest:testCannotCurateERC20EmptyURI() (gas: 15797)
CurationTest:testCannotCurateERC20IfNotApproval() (gas: 21624)
Expand Down
2 changes: 1 addition & 1 deletion src/Billboard/Billboard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ contract Billboard is IBillboard {
// revert if auction is not cleared
address _highestBidder = registry.highestBidder(tokenId_, epoch_);
IBillboardRegistry.Bid memory _highestBid = registry.getBid(tokenId_, epoch_, _highestBidder);
require(!_highestBid.isWon, "Auction not cleared");
require(_highestBid.isWon, "Auction not cleared");

IBillboardRegistry.Bid memory _bid = registry.getBid(tokenId_, epoch_, msg.sender);
uint256 amount = _bid.price + _bid.tax;
Expand Down
2 changes: 1 addition & 1 deletion src/Billboard/BillboardRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ contract BillboardRegistry is IBillboardRegistry, ERC721 {
bool isWithdrawn_
) external isFromOperator {
bids[tokenId_][epoch_][bidder_].isWithdrawn = isWithdrawn_;
emit BidWithdrawn(tokenId_, epoch_, msg.sender);
emit BidWithdrawn(tokenId_, epoch_, bidder_);
}

//////////////////////////////
Expand Down
294 changes: 131 additions & 163 deletions src/test/Billboard/BillboardTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,138 @@ contract BillboardTest is BillboardTestBase {
}
}

function testWithdrawBid(uint96 _price) public {
vm.assume(_price > 0.001 ether);

(uint256 _tokenId, IBillboardRegistry.Board memory _board) = _mintBoard();
uint256 _epoch = operator.getEpochFromBlock(block.number, _board.epochInterval);
uint256 _tax = operator.calculateTax(_tokenId, _price);
uint256 _total = _price + _tax;
uint256 _clearedAt = operator.getBlockFromEpoch(_epoch + 1, _board.epochInterval);

// new bid with USER_A
_placeBid(_tokenId, _epoch, USER_A, _price);

// new bid with USER_B
_placeBid(_tokenId, _epoch, USER_B, _price);

// clear auction
vm.roll(_clearedAt);
operator.clearAuction(_tokenId, _epoch);

// check bid
IBillboardRegistry.Bid memory _bidA = registry.getBid(_tokenId, _epoch, USER_A);
assertEq(_bidA.isWon, true);
IBillboardRegistry.Bid memory _bidB = registry.getBid(_tokenId, _epoch, USER_B);
assertEq(_bidB.isWon, false);

// withdraw bid
vm.expectEmit(true, true, true, false);
emit IBillboardRegistry.BidWithdrawn(_tokenId, _epoch, USER_B);

vm.prank(USER_B);
operator.withdrawBid(_tokenId, _epoch);

// check balances
assertEq(usdt.balanceOf(USER_A), 0);
assertEq(usdt.balanceOf(USER_B), _total);
}

function testCannotWithdrawBidTwice(uint96 _price) public {
vm.assume(_price > 0.001 ether);

(uint256 _tokenId, IBillboardRegistry.Board memory _board) = _mintBoard();
uint256 _epoch = operator.getEpochFromBlock(block.number, _board.epochInterval);
uint256 _tax = operator.calculateTax(_tokenId, _price);
uint256 _total = _price + _tax;
uint256 _clearedAt = operator.getBlockFromEpoch(_epoch + 1, _board.epochInterval);

// new bid with USER_A
_placeBid(_tokenId, _epoch, USER_A, _price);

// new bid with USER_B
_placeBid(_tokenId, _epoch, USER_B, _price);

// clear auction
vm.roll(_clearedAt);
operator.clearAuction(_tokenId, _epoch);

// withdraw bid
vm.prank(USER_B);
operator.withdrawBid(_tokenId, _epoch);
assertEq(usdt.balanceOf(USER_B), _total);

// withdraw bid again
vm.prank(USER_B);
vm.expectRevert("Bid already withdrawn");
operator.withdrawBid(_tokenId, _epoch);
}

function testCannotWithdrawBidIfWon(uint96 _price) public {
vm.assume(_price > 0.001 ether);

(uint256 _tokenId, IBillboardRegistry.Board memory _board) = _mintBoard();
uint256 _epoch = operator.getEpochFromBlock(block.number, _board.epochInterval);
uint256 _clearedAt = operator.getBlockFromEpoch(_epoch + 1, _board.epochInterval);

// new bid with USER_A
_placeBid(_tokenId, _epoch, USER_A, _price);

// new bid with USER_B
_placeBid(_tokenId, _epoch, USER_B, _price);

// clear auction
vm.roll(_clearedAt);
operator.clearAuction(_tokenId, _epoch);

// withdraw bid
vm.prank(USER_A);
vm.expectRevert("Bid already won");
operator.withdrawBid(_tokenId, _epoch);
}

function testCannotWithdrawBidIfAuctionNotEndedOrCleared(uint96 _price) public {
vm.assume(_price > 0.001 ether);

(uint256 _tokenId, IBillboardRegistry.Board memory _board) = _mintBoard();
uint256 _epoch = operator.getEpochFromBlock(block.number, _board.epochInterval);
uint256 _clearedAt = operator.getBlockFromEpoch(_epoch + 1, _board.epochInterval);

// new bid with USER_A
_placeBid(_tokenId, _epoch, USER_A, _price);

// auction is not ended
vm.roll(_clearedAt - 1);
vm.expectRevert("Auction not ended");
operator.withdrawBid(_tokenId, _epoch);

// auction is ended but not cleared
vm.roll(_clearedAt);
vm.expectRevert("Auction not cleared");
operator.withdrawBid(_tokenId, _epoch);
}

function testCannotWithdrawBidIfNotFound(uint96 _price) public {
vm.assume(_price > 0.001 ether);

(uint256 _tokenId, IBillboardRegistry.Board memory _board) = _mintBoard();
uint256 _epoch = operator.getEpochFromBlock(block.number, _board.epochInterval);
uint256 _clearedAt = operator.getBlockFromEpoch(_epoch + 1, _board.epochInterval);

// new bid with USER_A
_placeBid(_tokenId, _epoch, USER_A, _price);

// clear auction
vm.roll(_clearedAt);
operator.clearAuction(_tokenId, _epoch);

vm.prank(USER_B);
vm.expectRevert("Bid not found");
operator.withdrawBid(_tokenId, _epoch);
}

//////////////////////////////
/// Tax & Withdraw
/// Tax
//////////////////////////////

// function testCalculateTax() public {
Expand Down Expand Up @@ -586,168 +716,6 @@ contract BillboardTest is BillboardTestBase {
// operator.withdrawTax();
// }

// function testWithdrawBid(uint96 _price) public {
// vm.assume(_price > 0.001 ether);

// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _tax = operator.calculateTax(_price);
// uint256 _total = _price + _tax;

// // new auction and new bid with USER_A
// deal(address(usdt), USER_A, _total);
// vm.prank(USER_A);
// operator.placeBid(_tokenId, _price);

// // new bid with USER_B
// deal(address(usdt), USER_B, _total);
// vm.prank(USER_B);
// operator.placeBid(_tokenId, _price);

// // clear auction
// vm.roll(block.number + registry.leaseTerm() + 1);
// operator.clearAuction(_tokenId);

// // check auction
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);
// IBillboardRegistry.Auction memory _auction = registry.getAuction(_tokenId, _nextAuctionId);
// assertEq(_auction.highestBidder, USER_A);

// // check bid
// IBillboardRegistry.Bid memory _bidA = registry.getBid(_tokenId, _nextAuctionId, USER_A);
// assertEq(_bidA.isWon, true);
// IBillboardRegistry.Bid memory _bidB = registry.getBid(_tokenId, _nextAuctionId, USER_B);
// assertEq(_bidB.isWon, false);

// // withdraw bid
// vm.expectEmit(true, true, true, true);
// emit IBillboardRegistry.BidWithdrawn(_tokenId, _nextAuctionId, USER_B, _price, _tax);

// vm.prank(USER_B);
// operator.withdrawBid(_tokenId, _nextAuctionId);
// assertEq(usdt.balanceOf(USER_B), _total);
// }

// function testCannotWithBidTwice(uint96 _price) public {
// vm.assume(_price > 0.001 ether);

// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _tax = operator.calculateTax(_price);
// uint256 _total = _price + _tax;

// // new auction and new bid with USER_A
// deal(address(usdt), USER_A, _total);
// vm.prank(USER_A);
// operator.placeBid(_tokenId, _price);

// // new bid with USER_B
// deal(address(usdt), USER_B, _total);
// vm.prank(USER_B);
// operator.placeBid(_tokenId, _price);

// // clear auction
// vm.roll(block.number + registry.leaseTerm() + 1);
// operator.clearAuction(_tokenId);

// // check auction
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);
// IBillboardRegistry.Auction memory _auction = registry.getAuction(_tokenId, _nextAuctionId);
// assertEq(_auction.highestBidder, USER_A);

// // withdraw bid
// vm.prank(USER_B);
// operator.withdrawBid(_tokenId, _nextAuctionId);
// assertEq(usdt.balanceOf(USER_B), _total);

// // withdraw bid again
// vm.prank(USER_B);
// vm.expectRevert("Bid already withdrawn");
// operator.withdrawBid(_tokenId, _nextAuctionId);
// }

// function testCannotWithdrawBidIfWon(uint96 _price) public {
// vm.assume(_price > 0.001 ether);

// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _tax = operator.calculateTax(_price);
// uint256 _total = _price + _tax;

// // new auction and new bid with USER_A
// deal(address(usdt), USER_A, _total);
// vm.prank(USER_A);
// operator.placeBid(_tokenId, _price);

// // clear auction
// vm.roll(block.number + registry.leaseTerm() + 1);
// operator.clearAuction(_tokenId);

// // check auction
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);
// IBillboardRegistry.Auction memory _auction = registry.getAuction(_tokenId, _nextAuctionId);
// assertEq(_auction.highestBidder, USER_A);

// // withdraw bid
// vm.prank(USER_A);
// vm.expectRevert("Bid already won");
// operator.withdrawBid(_tokenId, _nextAuctionId);
// }

// function testCannotWithdrawBidIfAuctionNotEnded(uint96 _price) public {
// vm.assume(_price > 0.001 ether);

// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _tax = operator.calculateTax(_price);
// uint256 _total = _price + _tax;

// // new auction and new bid with USER_A
// vm.startPrank(USER_A);
// deal(address(usdt), USER_A, _total);
// operator.placeBid(_tokenId, _price);

// // auction is not ended
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);
// vm.expectRevert("Auction not ended");
// operator.withdrawBid(_tokenId, _nextAuctionId);

// // auction is ended but not cleared
// vm.roll(block.number + registry.leaseTerm() + 1);
// vm.expectRevert("Auction not cleared");
// operator.withdrawBid(_tokenId, _nextAuctionId);
// }

// function testCannotWithdrawBidIfAuctionNotCleared(uint96 _price) public {
// vm.assume(_price > 0.001 ether);

// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _tax = operator.calculateTax(_price);
// uint256 _total = _price + _tax;

// // new auction and new bid with USER_A
// deal(address(usdt), USER_A, _total);
// vm.prank(USER_A);
// operator.placeBid(_tokenId, _price);

// // new bid with USER_B
// deal(address(usdt), USER_B, _total);
// vm.prank(USER_B);
// operator.placeBid(_tokenId, _price);

// // auction is ended but not cleared
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);
// vm.roll(block.number + registry.leaseTerm() + 1);
// vm.prank(USER_B);
// vm.expectRevert("Auction not cleared");
// operator.withdrawBid(_tokenId, _nextAuctionId);
// }

// function testCannotWithdrawBidIfNotFound() public {
// (uint256 _tokenId, ) = _mintBoardAndPlaceBid();
// uint256 _nextAuctionId = registry.nextBoardAuctionId(_tokenId);

// vm.prank(USER_A);
// vm.expectRevert("Bid not found");
// operator.withdrawBid(_tokenId, _nextAuctionId);
// }

//////////////////////////////
/// ERC20 & ERC721 related
//////////////////////////////
Expand Down

0 comments on commit db48341

Please sign in to comment.