Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent batch auction cancellations during final 10% of auction #1203

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion contracts/plugins/trading/GnosisTrade.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ contract GnosisTrade is ITrade, Versioned {
TradeKind public constant KIND = TradeKind.BATCH_AUCTION;
uint256 public constant FEE_DENOMINATOR = 1000;

// Can only cancel order in first 90% of the auction
uint192 public constant CANCEL_WINDOW = 9e17; // {1} first 90% of auction

// Upper bound for the max number of orders we're happy to have the auction clear in;
// When we have good price information, this determines the minimum buy amount per order.
uint96 public constant MAX_ORDERS = 5000; // bounded to avoid going beyond block gas limit
Expand Down Expand Up @@ -141,10 +144,15 @@ contract GnosisTrade is ITrade, Versioned {
// amount is > 0 and < type(uint256).max.
AllowanceLib.safeApproveFallbackToMax(address(sell), address(gnosis), req.sellAmount);

// Can only cancel within the CANCEL_WINDOW
uint48 cancellationEndTime = uint48(
block.timestamp + (batchAuctionLength * CANCEL_WINDOW) / FIX_ONE
);

auctionId = gnosis.initiateAuction(
sell,
buy,
endTime,
cancellationEndTime,
endTime,
_sellAmount,
minBuyAmount,
Expand Down
41 changes: 41 additions & 0 deletions test/integration/EasyAuction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,47 @@ describeFork(`Gnosis EasyAuction Mainnet Forking - P${IMPLEMENTATION}`, function
expect(await rsr.balanceOf(backingManager.address)).to.equal(0)
})

it('cannot cancel in last 10% of auction', async () => {
// Place 2 orders
const bidAmt = buyAmt.add(1)
await token0.connect(addr1).approve(easyAuction.address, bidAmt.mul(3))
await easyAuction
.connect(addr1)
.placeSellOrders(auctionId, [sellAmt], [bidAmt], [QUEUE_START], ethers.constants.HashZero)
await easyAuction
.connect(addr1)
.placeSellOrders(
auctionId,
[sellAmt],
[bidAmt.mul(2)],
[QUEUE_START],
ethers.constants.HashZero
)

// Advance halfway
await advanceTime(config.batchAuctionLength.div(2).toString())

// Cancel successfully
const OrderHelperFactory = await ethers.getContractFactory('IterableOrderedOrderSetWrapper')
const orderHelper = await OrderHelperFactory.deploy()
const userId = await easyAuction.callStatic.getUserId(addr1.address)
const order = await orderHelper.encodeOrder(userId, sellAmt, bidAmt)
await easyAuction.connect(addr1).cancelSellOrders(auctionId, [order])

// Advance near end
await advanceTime(config.batchAuctionLength.div(2).sub(10).toString())

// Cannot cancel
const order2 = await orderHelper.encodeOrder(userId, sellAmt, bidAmt.mul(2))
await expect(
easyAuction.connect(addr1).cancelSellOrders(auctionId, [order2])
).to.be.revertedWith('no longer in order placement and cancelation phase')

// End auction
await advanceTime(config.batchAuctionLength.div(2).toString())
await easyAuction.settleAuction(auctionId)
})

it('full volume -- bid at 2x price', async () => {
const bidAmt = buyAmt.add(1)
sellAmt = sellAmt.div(2)
Expand Down
Loading