Skip to content

fix(dpp): bind SetPriceForDirectPurchase action_id to full pricing schedule#3357

Merged
QuantumExplorer merged 4 commits into
v3.1-devfrom
fix/set-price-action-id-bind-payload
Mar 17, 2026
Merged

fix(dpp): bind SetPriceForDirectPurchase action_id to full pricing schedule#3357
QuantumExplorer merged 4 commits into
v3.1-devfrom
fix/set-price-action-id-bind-payload

Conversation

@QuantumExplorer
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer commented Mar 17, 2026

Issue being fixed or feature implemented

Same class of vote-swap vulnerability as PR #3346, but for TokenSetPriceForDirectPurchaseTransition.

The action_id only hashed minimum_purchase_amount_and_price().1 (the credit price of the lowest tier), so different pricing schedules with the same minimum-tier price produced identical action_ids. A malicious group member could propose a fair pricing schedule, collect votes, then swap to a predatory schedule.

Collision examples:

  • SetPrices({1: 100, 10: 800}) vs SetPrices({1: 100, 10: 9999}) — same min price, different tiers
  • SinglePrice(100) vs SetPrices({1: 100}) — different types, same (1, 100) result
  • SetPrices({5: 100, ...}) vs SetPrices({10: 100, ...}) — different minimum amounts, same price

What was done?

Replaced minimum_purchase_amount_and_price().1.to_be_bytes() with bincode::encode_to_vec(price_per_token, bincode::config::standard()) — the full serialized pricing schedule is now included in the hash.

Not gated behind a platform version because SetPriceForDirectPurchase is a new v3.1 feature not yet used in production.

How Has This Been Tested?

4 new tests proving:

  1. Different SetPrices with same minimum produce different action_ids
  2. SinglePrice(100) vs SetPrices({1: 100}) produce different action_ids
  3. Identical schedules produce the same action_id
  4. None price vs Some price produce different action_ids
test result: ok. 4 passed; 0 failed

Breaking Changes

This changes action_id computation for SetPriceForDirectPurchase transitions. Since this feature has not been used in production, there are no backward compatibility concerns.

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 made corresponding changes to the documentation if needed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved action ID calculation to distinguish full pricing schedules (prevents schedule-swaps being treated as identical).
  • Chores

    • Introduced a version flag for token pricing action ID behavior so platforms can opt between legacy and new calculation logic.
  • Tests

    • Added unit tests covering cross-version and varied pricing-schedule scenarios to ensure consistent, distinct action IDs.

@github-actions github-actions Bot added this to the v3.1.0 milestone Mar 17, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 17, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Added a versioned action-id calculation for TokenSetPriceForDirectPurchaseTransition: a public dispatcher calculate_action_id_with_fields routes to v0 (backward-compatible) or v1 (hashes full serialized TokenPricingSchedule). Platform-version flag and tests were added; unknown versions return an explicit error.

Changes

Cohort / File(s) Summary
TokenSetPrice Transition Core
packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_set_price_for_direct_purchase_transition/v0_methods.rs
Added pub fn calculate_action_id_with_fields(...) -> Result<Identifier, ProtocolError> implementing version dispatch. Introduced private calculate_action_id_with_fields_v0 and ..._v1 paths; v1 hashes full serialized TokenPricingSchedule (bincode).
V0 Trait impl / Call sites
packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_set_price_for_direct_purchase_transition/v0/v0_methods.rs
Updated calculate_action_id to accept platform_version and delegate to the new versioned calculate_action_id_with_fields, changing call signature and control flow to use platform-versioned behavior.
Platform versioning
packages/rs-platform-version/src/version/dpp_versions/dpp_token_versions/mod.rs, .../v1.rs, .../v2.rs, .../v12.rs
Added new field token_set_price_action_id_version: FeatureVersion to DPPTokenVersions; initialized to 0 in v1 and 1 in v2. Minor comment update in v12.rs. Review initialization and compatibility across versions.
Tests / Test helpers
packages/rs-dpp/src/state_transition/.../token_set_price_for_direct_purchase_transition/... (tests in same module)
Added unit tests covering: distinct action_ids for different schedules despite same minimum, SinglePrice vs SetPrices differentiation, identical schedules matching, and cross-version (v0 vs v1) differences. Included helper make_transition for v0 tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hashed the whole schedule, not just a part,
So swaps and surprises no longer dart,
Versions now choose which path to take,
Tests nibble carrots for correctness' sake,
Hop, hop — identifiers behave! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: binding the SetPriceForDirectPurchase action_id to the full pricing schedule to prevent vote-swap vulnerabilities.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/set-price-action-id-bind-payload
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 17, 2026

Codecov Report

❌ Patch coverage is 93.45238% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.51%. Comparing base (5e7d433) to head (48447ca).
⚠️ Report is 1 commits behind head on v3.1-dev.

Files with missing lines Patch % Lines
...price_for_direct_purchase_transition/v0_methods.rs 93.16% 11 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           v3.1-dev    #3357      +/-   ##
============================================
+ Coverage     75.50%   75.51%   +0.01%     
============================================
  Files          2912     2912              
  Lines        281065   281224     +159     
============================================
+ Hits         212211   212363     +152     
- Misses        68854    68861       +7     
Components Coverage Δ
dpp 63.52% <93.45%> (+0.08%) ⬆️
drive 81.64% <ø> (ø)
drive-abci 85.99% <ø> (ø)
sdk 31.25% <ø> (ø)
dapi-client 79.06% <ø> (ø)
platform-version ∅ <ø> (∅)
platform-value 58.46% <ø> (ø)
platform-wallet 60.40% <ø> (ø)
drive-proof-verifier 48.00% <ø> (ø)
🚀 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.

@QuantumExplorer QuantumExplorer force-pushed the fix/set-price-action-id-bind-payload branch from bc5bd95 to 9d271e2 Compare March 17, 2026 05:15
@QuantumExplorer QuantumExplorer changed the base branch from v3.1-dev to fix/token-config-action-id-bind-payload March 17, 2026 05:15
Base automatically changed from fix/token-config-action-id-bind-payload to v3.1-dev March 17, 2026 05:19
QuantumExplorer and others added 2 commits March 17, 2026 12:21
…hedule

The action_id for TokenSetPriceForDirectPurchaseTransition only hashed
minimum_purchase_amount_and_price().1 (the credit price of the lowest
tier). This meant different pricing schedules with the same minimum-tier
price produced identical action_ids, enabling the same vote-swap attack
as the token config update vulnerability fixed in PR #3346.

Examples of collisions in the old code:
- SetPrices({1: 100, 10: 800}) vs SetPrices({1: 100, 10: 9999})
- SinglePrice(100) vs SetPrices({1: 100})
- SetPrices({5: 100, ...}) vs SetPrices({10: 100, ...})

Fix: serialize the full TokenPricingSchedule with bincode and include
it in the hash. This binds the voted-on pricing schedule into the
action_id, preventing vote-swap attacks.

Note: Unlike the config update fix, this is NOT gated behind a platform
version because SetPriceForDirectPurchase is a new feature (v3.1) that
has not been used in production yet. There is no backward compatibility
concern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- calculate_action_id_with_fields returns Result with map_err instead
  of using expect for bincode encoding
- Update wrapper and v0 impls to match the AllowedAsMultiPartyAction
  trait signature from #3346 (platform_version + Result)
- Fix all tests to pass platform_version and unwrap Results
- Rebase on #3346 branch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer force-pushed the fix/set-price-action-id-bind-payload branch from 9d271e2 to b64180b Compare March 17, 2026 05:21
@github-actions
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: "94ddab4d078a45fa7a7bca7acb5121680abfb92ef0e020c1f6cf14e527c6fe90"
)

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.

QuantumExplorer and others added 2 commits March 17, 2026 13:10
Gate the action_id fix behind platform version, matching the pattern
from #3346 (token config update):

- Add token_set_price_action_id_version field to DPPTokenVersions
- v0: hashes only minimum_purchase_amount_and_price().1 (existing)
- v1: hashes the full serialized TokenPricingSchedule (fix)
- Create TOKEN_VERSIONS_V3 with both fixes enabled
- Update v12 to use TOKEN_VERSIONS_V3
- Add v0 vulnerability regression test and v0-vs-v1 differentiation test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TOKEN_VERSIONS_V2 hasn't activated in production yet, so there's no
need for a separate V3. Set token_set_price_action_id_version: 1
directly in V2 alongside token_config_update_action_id_version: 1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member Author

@QuantumExplorer QuantumExplorer left a comment

Choose a reason for hiding this comment

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

Self Reviewed

Copy link
Copy Markdown
Member Author

@QuantumExplorer QuantumExplorer left a comment

Choose a reason for hiding this comment

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

Approved

@QuantumExplorer QuantumExplorer merged commit f89fe85 into v3.1-dev Mar 17, 2026
14 of 15 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/set-price-action-id-bind-payload branch March 17, 2026 06:22
QuantumExplorer added a commit that referenced this pull request Mar 17, 2026
…hedule (#3357)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant