penumbra-zone / web

Apache License 2.0
10 stars 7 forks source link

Use localSeq for determining which sequence number Prax has saved for an auction #1297

Closed jessepinho closed 1 week ago

jessepinho commented 1 week ago

Full context for this PR, if reviewers are interested:

Dutch auctions have a concept of a "sequence number", which represents which state the auction is in. 0 means the auction is open, 1 means it's closed, and 2+ means the user has withdrawn the funds from the auction after it's closed. (The user can theoretically do an infinite number of withdrawals, but the first withdrawal results in all funds being withdrawn, so any future withdrawals have no financial impact. For this reason, minifront only shows a Withdraw button for auctions with a sequence number of 1, and hides the Withdraw button if the sequence number is >= 2.)

These sequence states are encoded into the NFTs the user holds for those auctions. So, when a user starts an auction, they get an NFT with the prefix auctionnft_0_pauctid1... The 0 in the token name refers to the sequence number.

When a user ends an auction, they exchange their auctionnft_0_... for an auctionnft_1_.... Similarly, when they withdraw funds from an auction, they change their auctionnft_1_... for an auctionnft_2_.... A user can only exchange an auction NFT of sequence number N for an auction NFT of sequence number N + 1 — that is, they can't jump from auctionnft_0_... to auctionnft_2_....

The user can end an auction while it's in progress, or after the allotted time (measured in number of blocks) for that auction has passed. Regardless of when the user ends an auction, they have to take the manual action of ending the auction for their auctionnft_0_... to be exchanged for an auctionnft_1_.... That is, the chain doesn't automatically exchange their tokens for them — they have to do it themselves, even if the auction's allotted time has already passed.

This is where things can get a little out of sync between the user's client (Prax) and the fullnode. The fullnode automatically considers an auction to have a sequence number of 1 once the allotted time has passed (ignoring, for a moment, the case where the user manually ends the auction sooner). But the user's NFT won't reflect that sequence number until the user manually ends the auction; that is, the user will have an auctionnft_0_... even though the fullnode consider the auction to have a sequence number of 1. This causes a problem when the user clicks the "Query latest state" button:

image

That button queries the fullnode for the auction state, at which point minifront gets back a response showing the auction state as 1. Then, minifront would render a Withdraw button rather than an End button, since the auction has ended (as far as the fullnode is concerned). But the problem is, the user still has an auctionnft_0_..., and thus the user needs to end the auction before they can withdraw funds from it.

To fix this, the core team introduced a local_seq property on AuctionsResponse that reflects the local view service's version of the sequence number, which may lag behind the fullnode's, but will always be in sync with which version of the auction NFT the user holds because it is updated whenever the user exchanges one auction NFT for another. This property can then be used to correctly determine which button to show, and prevent showing the "Withdraw" button to the user when they can't yet withdraw.

Closes #1285 Closes #1242

changeset-bot[bot] commented 1 week ago

🦋 Changeset detected

Latest commit: 50318aa9ed9565d801a61fa6997e41a400eb5f07

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages | Name | Type | | ----------------------- | ----- | | @penumbra-zone/services | Patch | | minifront | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR