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

revert on failed status update after authorizeOrder call #30

Merged
merged 2 commits into from
Feb 28, 2024

Conversation

0age
Copy link
Contributor

@0age 0age commented Feb 27, 2024

No description provided.

bool revertOnInvalid
) internal pure returns (bool revertOnFailedUpdate) {
assembly {
revertOnFailedUpdate := or(revertOnInvalid, gt(orderType, 1))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just explaining in my own words to check my understanding: we want to always provide revertOnInvalid to _updateStatus because at this point, for restricted (and contract, technically) orders, we already called the pre-hook, which could have modified state. If we fail updating the status (eg order was already filled or cannot apply the supplied fraction) for an order in the fulfillAvailable case, we want to revert rather than simply mark as "unavailable" and continue, because the authorizeOrder call is stateful, and we won't call the complementary validateOrder call for "unavailable" orders (and the supplied spent/received items would not technically be correct in either case).

@@ -507,7 +511,10 @@ contract OrderCombiner is OrderFulfiller, FulfillmentApplier {
orderHash,
advancedOrder.numerator,
advancedOrder.denominator,
revertOnInvalid
_revertOnFailedUpdate(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we get here _checkRestrictedAdvancedOrderAuthorization must have returned isValid=true (otherwise we continue the loop). Then if it's a restricted order and the update fails we always revert.
I get the idea: authorizeOrder was called and therefore we cannot skip this order anymore because we would also skip the corresponding validateOrder call later, so we revert.

An edge-case is that _checkRestrictedAdvancedOrderAuthorization can return true for restricted orders even if no authorizeOrder call was done, i.e., when the caller is the zone itself. So it seems to be more restrictive than it needs to be as skipping in the case of caller == zone should still work fine? Not saying that we have to fix this edge-case, just pointing it out.
And of course, if a fulfillAvailable overfills an order and updateStatus returns false, you're reverting the entire tx now instead of just skipping the orders that would overfill. Doesn't this kind of go against what fulfillAvailable was designed for? Let's say I want to buy up to 5 NFTs, so I create 5 orders buying 1 each, but there are only 4 available now. It would revert?

(If the fix for the other issue ends up simulating the updated order fill sizes already in the validation step, you might be able to detect early which orders can be skipped, essentially updateStatus calls should then never fail and it would fix this problem too.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point about the edge case — will try adding it in (hopefully it doesn't exceed stack depth!)

I agree that it's not optimal to revert the whole batch in these cases, but in practice this will only occur when fulfilling the same order multiple times; and there's still a workaround if you have the zone itself track the remaining fill fraction using tstore

If we come up with an effective way to track fill fractions in flight then we can always roll this change back, but IMHO it's more important to guarantee that the authorizeOrder invariants are upheld than that orders will always be skipped if possible

@0age
Copy link
Contributor Author

0age commented Feb 28, 2024

Merging, but leaving a note that if we take a different approach with _updateStatus then we should be able to relax this constraint

@0age 0age merged commit 2ae3888 into main Feb 28, 2024
3 checks passed
@0age 0age deleted the fix-authorizeOrder-skip branch February 28, 2024 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants