Skip to content

fix(drive): return error instead of panicking on empty SetPrices direct purchase#3856

Merged
QuantumExplorer merged 2 commits into
v3.1-devfrom
claude/ecstatic-goodall-f03d43
Jun 11, 2026
Merged

fix(drive): return error instead of panicking on empty SetPrices direct purchase#3856
QuantumExplorer merged 2 commits into
v3.1-devfrom
claude/ecstatic-goodall-f03d43

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Jun 11, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Hardens the token direct-purchase transition against an edge case in tiered (SetPrices) pricing schedules. In an unusual schedule configuration the transformer could fail ungracefully instead of returning a clean validation error.

What was done?

Reworked the no-matching-tier branch of the direct-purchase transformer so it no longer makes an assumption about the schedule's contents. When no applicable price tier is found, the transition is rejected with an appropriate consensus error in all cases. Added a regression test covering the edge case.

How Has This Been Tested?

  • cargo test -p drive-abci --lib direct_selling — all tests pass, including the new regression test and the existing version-pinned baselines (existing behaviour unchanged).
  • cargo check -p drive, cargo clippy -p drive, cargo fmt --all — clean.

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Direct token purchases with empty pricing schedules now fail gracefully with a clear "not for direct sale" error instead of causing a panic.
    • Purchases below the minimum tier are rejected with a specific "amount under minimum" error.
  • Tests

    • Added regression tests covering empty pricing schedules and below-minimum direct purchase attempts.

…ct purchase

A token's pricing authority can set an empty `SetPrices` schedule
(`Some(SetPrices({}))`): structure validation explicitly skips the price,
state validation is auth-only, and apply stores it verbatim. A later
`TokenDirectPurchase` then hits the `None` arm of
`set_prices.range(..=token_count).next_back()`, which called
`set_prices.keys().next().expect("Map is not empty")` — panicking on the empty
map. This transform runs on every validator during block execution, so the
panic (via the global panic hook) crashes all validators and halts the chain.

Handle the empty schedule without panicking: when the schedule has no tiers,
return a `TokenNotForDirectSale` consensus error; otherwise keep the existing
`TokenAmountUnderMinimumSaleAmount` behaviour. Adds an end-to-end regression
test that plants an empty `SetPrices` and asserts the purchase is rejected
gracefully (no panic, buyer receives no tokens).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thepastaclaw

thepastaclaw commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

✅ Review complete (commit 7009115)

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3e64e4d-b291-40f2-97b7-671d0f7ee713

📥 Commits

Reviewing files that changed from the base of the PR and between 6858928 and 7009115.

📒 Files selected for processing (1)
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs

📝 Walkthrough

Walkthrough

Avoid a validator panic by handling empty TokenPricingSchedule::SetPrices in the direct-purchase transformer; return TokenNotForDirectSale for empty schedules and TokenAmountUnderMinimumSaleAmount when below the minimum. Add regression tests for both empty and below-minimum cases.

Changes

Token Direct Purchase Panic Prevention

Layer / File(s) Summary
Empty schedule validation in transformer
packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_direct_purchase_transition_action/v0/transformer.rs
Updated error handling when no matching tier is found: check whether SetPrices contains any tiers and return TokenAmountUnderMinimumSaleAmount if tiers exist or TokenNotForDirectSale if the schedule is empty, removing an unsafe expect() that could panic.
Regression tests for empty and below-minimum schedules
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs
Added test_direct_purchase_empty_set_prices_does_not_panic to assert empty SetPrices yields TokenNotForDirectSale without panicking, and test_direct_purchase_below_minimum_sale_amount to assert purchases below the smallest tier yield TokenAmountUnderMinimumSaleAmount; both confirm buyer balance remains None.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

bug

Suggested reviewers

  • thepastaclaw

Poem

🐰 A tiny map once caused a fright,
Empty tiers hid from the light.
Now checks are safe, no panic springs,
Errors returned on cautious wings.
Hop, patch, and let the ledger sing!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main fix: preventing a panic on empty SetPrices during direct purchase transitions by returning an error instead.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/ecstatic-goodall-f03d43

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Reviewed

@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.16%. Comparing base (93b657d) to head (7009115).

Additional details and impacted files
@@            Coverage Diff            @@
##           v3.1-dev    #3856   +/-   ##
=========================================
  Coverage     87.15%   87.16%           
=========================================
  Files          2641     2641           
  Lines        327793   327798    +5     
=========================================
+ Hits         285701   285730   +29     
+ Misses        42092    42068   -24     
Components Coverage Δ
dpp 87.66% <ø> (ø)
drive 86.06% <100.00%> (+0.01%) ⬆️
drive-abci 89.40% <ø> (ø)
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.20% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 49.55% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Code Review

All six reviewers converged: no in-scope findings. The PR is a tight, well-scoped fix replacing a chain-halt .expect() panic with a safe match returning TokenNotForDirectSale for empty SetPrices schedules, with a focused regression test. Out-of-scope follow-ups (rejecting empty schedules at the write boundary) are noted for maintainer triage but do not affect the review action.

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "59a6da4fb5d049353852792570c2112b9494cd8e6691ef22810cba5451a1d52d"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

Adds a direct-purchase test for a non-empty tiered SetPrices schedule whose
smallest tier exceeds the requested amount, exercising the
TokenAmountUnderMinimumSaleAmount path alongside the existing empty-schedule
(TokenNotForDirectSale) regression test — covering both arms of the
no-matching-tier branch added by this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Code Review

Cumulative review of PR #3856 at head 7009115 confirms the fix correctly replaces a chain-halting .expect("Map is not empty") panic with deterministic consensus errors (TokenNotForDirectSale for empty SetPrices, TokenAmountUnderMinimumSaleAmount for non-empty below-minimum), preserving the existing BumpIdentityDataContractNonceAction fee/nonce path. The latest delta (685892..700911) is test-only, adding the below-minimum regression test to complement the existing empty-schedule test. All six agents independently found no issues; no in-scope blocking, suggestion, or nitpick findings.

@QuantumExplorer
QuantumExplorer merged commit 6a2e9e6 into v3.1-dev Jun 11, 2026
21 checks passed
@QuantumExplorer
QuantumExplorer deleted the claude/ecstatic-goodall-f03d43 branch June 11, 2026 21:28
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.

2 participants