Block same-timestamp Predict mint and redeem (DBU-472)#1085
Merged
sdelo merged 4 commits intoJun 25, 2026
Conversation
Record each position's open time (clock.timestamp_ms()) at mint and reject a live redeem whose timestamp equals it. A single transaction reads one Clock, so this closes the atomic mint -> oracle-update -> redeem arbitrage that would round-trip a freshly minted order against a price the same tx pushed. The open time is carried forward across partial-close replacements, so seasoned positions stay closable in multiple steps. DPU-472 Co-authored-by: Cursor <cursoragent@cursor.com>
Move the open-time comparison into a factual predict_account assertion (assert_not_opened_at, owning the open-time state) so the abort path is covered by running unit tests instead of only the disabled flow test: the same-timestamp abort (ESameTimestampRedeem), the missing-position abort, and the pass case that reads back the stored open time. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
Author
|
@claude review |
predict_account is position state only: expose a position_opened_at_ms getter and move the same-timestamp redeem assertion back into expiry_market::redeem_live_internal (EMintRedeemSameTimestamp), where the redeem flow owns the policy. The getter keeps its missing-position unit coverage; the abort path is covered by the disabled flow test. Co-authored-by: Cursor <cursoragent@cursor.com>
…c-mint-oracle-redeem Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # packages/predict/sources/expiry_market.move
0xaslan
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
clock.timestamp_ms()) at mint, stored on the per-accountPositionrow inpredict_account.expiry_market::redeem_live->redeem_live_internal) whose timestamp equals the position's open time (EMintRedeemSameTimestamp). A single transaction reads oneClock, so equal timestamps mean the mint and redeem are in the same atomic transaction.mint -> update oracle -> redeemarbitrage: a freshly minted order can no longer be round-tripped against a price the same transaction just pushed.Key decisions
predict_accountowns the open-time state and exposes aposition_opened_at_msgetter;expiry_market::redeem_live_internalowns the redeem policy and does the!=assertion (EMintRedeemSameTimestamp).!=(the clock is monotonic non-decreasing, so this is equivalent to "the clock must have advanced").Test plan
sui move build --path packages/predict --warnings-are-errorsis green.sui move test --path packages/predict --gas-limit 100000000000is green (238 tests).predict_account_tests:position_opened_at_msround-trips the stored open time (including carry-forward across a partial-close replacement) and abortsEPositionNotFoundfor an unknown order.tests/flows/mint_redeem_guard_tests.move.disabled(same-tx redeem abortsEMintRedeemSameTimestamp; redeem succeeds once the clock advances). It is committed.disabledto match the rest of the root-dependent flow suite, which cannot run on the stable framework (noAccumulatorRoottest constructor); it should be re-enabled with them on the nightly framework.