Skip to content

9.5 upgrade & add underflow protection for referred volume#3261

Merged
jusbar23 merged 13 commits intomainfrom
9.5_upgrade
Dec 2, 2025
Merged

9.5 upgrade & add underflow protection for referred volume#3261
jusbar23 merged 13 commits intomainfrom
9.5_upgrade

Conversation

@jusbar23
Copy link
Contributor

@jusbar23 jusbar23 commented Nov 25, 2025

Changelist

  • Add 9.5 upgrade and underflow protection for ExpireOldStats

Test Plan

  • Unit tests

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Summary by CodeRabbit

  • New Features

    • v9.5 upgrade: migrates 30-day referred volumes into epoch-level statistics and registers a v9.5 upgrade handler.
  • Bug Fixes

    • Expiration logic now guards against numeric underflow when trimming old stats.
  • Tests

    • Added unit and container-style tests for the v9.5 migration (empty and multi-user scenarios); removed legacy v9.4 container test.
  • Chores

    • Bumped test/version files to v9.5.

✏️ Tip: You can customize this high-level summary in your review settings.

@jusbar23 jusbar23 requested a review from a team as a code owner November 25, 2025 17:00
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 25, 2025

Walkthrough

Adds a v9.5 upgrade that migrates users' 30-day referred volume into epoch-level stats, wires a v9.5 upgrade handler, adds underflow protection and an address-enumeration helper to the stats keeper, updates testing version files, adds unit and container tests for the migration, and removes the v9.4 container test.

Changes

Cohort / File(s) Summary
v9.5 upgrade package
protocol/app/upgrades/v9.5/constants.go, protocol/app/upgrades/v9.5/upgrade.go
Adds UpgradeName = "v9.5" and Upgrade variable; implements Migrate30dReferredVolumeToEpochStats and CreateUpgradeHandler to migrate per-user 30-day referred-volume into epoch stats and run migrations.
Stats keeper core
protocol/x/stats/keeper/keeper.go
Adds GetAllAddressesWithReferredVolume(ctx) and clamps affiliate-related uint64 fields to zero in ExpireOldStats to prevent underflow.
Stats keeper tests
protocol/x/stats/keeper/keeper_test.go
Adds tests TestExpireOldStats_UnderflowProtection* covering underflow guards, boundary, and multi-user scenarios.
v9.5 container & state tests
protocol/app/upgrades/v9.5/upgrade_container_test.go
Adds tests TestMigrate30dReferredVolumeToEpochStats, TestMigrate30dReferredVolumeToEpochStats_EmptyEpochStats, and state-upgrade scaffolding to validate migration end-to-end.
Removed v9.4 container test
protocol/app/upgrades/v9.4/upgrade_container_test.go
Deletes the v9.4 container upgrade test and its helper functions.
App upgrade wiring
protocol/app/upgrades.go
Replaces v_9_4 wiring with v_9_5: registers v_9_5.Upgrade, checks v_9_5.UpgradeName, and calls v_9_5.CreateUpgradeHandler with updated parameters (configurator, StatsKeeper, EpochsKeeper).
Version artifacts
protocol/testing/version/VERSION_CURRENT, protocol/testing/version/VERSION_FULL_NAME_PREUPGRADE, protocol/testing/version/VERSION_PREUPGRADE
Bumps protocol testing version strings (v9.4 → v9.5 and related preupgrade identifiers).

Sequence Diagram(s)

sequenceDiagram
    participant Operator as Upgrade Trigger
    participant Handler as CreateUpgradeHandler
    participant Migration as Migrate30dReferredVolumeToEpochStats
    participant Stats as StatsKeeper
    participant Epochs as EpochsKeeper
    participant MM as ModuleManager

    Operator->>Handler: start upgrade
    Handler->>Migration: run migration(ctx, statsKeeper, epochsKeeper)
    Migration->>Stats: GetAllAddressesWithReferredVolume()
    Stats-->>Migration: addresses[]

    rect rgba(150,200,255,0.14)
        note right of Migration: For each address with 30d referred volume
        Migration->>Epochs: GetCurrentEpoch()
        Epochs-->>Migration: epoch
        Migration->>Epochs: GetEpochStats(addr, epoch)
        Epochs-->>Migration: epochStats (or nil)
        Migration->>Migration: merge 30d referred volume -> epochStats
        Migration->>Epochs: SetEpochStats(updated)
        Migration->>Migration: log per-address migration
    end

    Handler->>MM: mm.RunMigrations(configurator)
    MM-->>Handler: done
    Handler-->>Operator: upgrade complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to migration idempotency, address deduplication, and logging verbosity.
  • Verify ExpireOldStats clamping covers all affiliate fields and maintains expected invariants.
  • Review new container tests for deterministic setup and potential flakiness.

Possibly related PRs

Suggested labels

feature:x/affiliates

Suggested reviewers

  • shrenujb
  • teddyding

Poem

🐰 A hop, a ledger shuffle — volumes take their place,
Thirty days tucked into each epoch's quiet space.
Counters guarded, no slips, no underflow fright,
Tests hop forward, making sure the numbers are right.
Hooray — the chain advances, neat and bright.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The description includes required sections (Changelist, Test Plan, Author/Reviewer Checklist) but lacks sufficient detail about the migration logic and scope of changes. Expand Changelist to describe the epoch stats migration and keeper method additions; clarify scope and type of state changes for proper labeling.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarizes the two main changes: adding v9.5 upgrade functionality and implementing underflow protection for referred volume handling.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 9.5_upgrade

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
protocol/x/stats/keeper/keeper_test.go (1)

1070-1075: Redundant assertions after confirming value is 0.

Lines 1065-1068 already assert the values equal 0. The subsequent require.Less assertions on lines 1072-1075 will always pass since 0 < 1000.

Consider removing these redundant checks or restructuring the test to use only one assertion style.

protocol/app/upgrades/v9.5/upgrade.go (1)

54-58: Unnecessary nil check: GetUserStats never returns nil.

Looking at keeper.go lines 149-160, GetUserStats always returns a pointer to a struct (either unmarshaled data or an empty &types.UserStats{}), never nil.

The nil check on line 56 will never be true and can be removed:

 globalUserStats := statsKeeper.GetUserStats(ctx, address)
-if globalUserStats == nil {
-    continue
-}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e58cce2 and 7cbeb01.

📒 Files selected for processing (5)
  • protocol/app/upgrades/v9.5/constants.go (1 hunks)
  • protocol/app/upgrades/v9.5/upgrade.go (1 hunks)
  • protocol/app/upgrades/v9.5/upgrade_test.go (1 hunks)
  • protocol/x/stats/keeper/keeper.go (2 hunks)
  • protocol/x/stats/keeper/keeper_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: hwray
Repo: dydxprotocol/v4-chain PR: 2597
File: indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql:16-20
Timestamp: 2024-11-22T18:12:04.606Z
Learning: Avoid suggesting changes to deprecated functions such as `dydx_update_perpetual_v1_handler` in `indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql` if they are unchanged in the PR.
📚 Learning: 2024-11-15T16:00:11.304Z
Learnt from: hwray
Repo: dydxprotocol/v4-chain PR: 2551
File: protocol/x/subaccounts/keeper/subaccount.go:852-865
Timestamp: 2024-11-15T16:00:11.304Z
Learning: The function `GetCrossInsuranceFundBalance` in `protocol/x/subaccounts/keeper/subaccount.go` already existed and was just moved in this PR; changes to its error handling may be out of scope.

Applied to files:

  • protocol/x/stats/keeper/keeper.go
  • protocol/x/stats/keeper/keeper_test.go
📚 Learning: 2024-11-15T15:59:28.095Z
Learnt from: hwray
Repo: dydxprotocol/v4-chain PR: 2551
File: protocol/x/subaccounts/keeper/subaccount.go:833-850
Timestamp: 2024-11-15T15:59:28.095Z
Learning: The function `GetInsuranceFundBalance` in `protocol/x/subaccounts/keeper/subaccount.go` already existed and was just moved in this PR; changes to its error handling may be out of scope.

Applied to files:

  • protocol/x/stats/keeper/keeper.go
📚 Learning: 2024-11-15T16:17:29.092Z
Learnt from: hwray
Repo: dydxprotocol/v4-chain PR: 2551
File: protocol/x/clob/types/expected_keepers.go:86-90
Timestamp: 2024-11-15T16:17:29.092Z
Learning: The function `GetCrossInsuranceFundBalance` in `protocol/x/clob/types/expected_keepers.go` already existed and was just moved in this PR; changes to its error handling may be out of scope.

Applied to files:

  • protocol/x/stats/keeper/keeper.go
  • protocol/x/stats/keeper/keeper_test.go
🧬 Code graph analysis (3)
protocol/x/stats/keeper/keeper.go (2)
protocol/x/stats/types/keys.go (1)
  • UserStatsKeyPrefix (21-21)
protocol/x/stats/types/stats.pb.go (3)
  • UserStats (459-471)
  • UserStats (475-475)
  • UserStats (476-478)
protocol/app/upgrades/v9.5/upgrade.go (4)
protocol/x/stats/keeper/keeper.go (1)
  • Keeper (23-30)
protocol/mocks/Configurator.go (1)
  • Configurator (15-17)
protocol/lib/context.go (1)
  • UnwrapSDKContext (31-55)
protocol/app/upgrades/v9.5/constants.go (1)
  • UpgradeName (9-9)
protocol/x/stats/keeper/keeper_test.go (1)
protocol/x/stats/types/stats.pb.go (15)
  • EpochStats (304-309)
  • EpochStats (313-313)
  • EpochStats (314-316)
  • EpochStats_UserWithStats (359-362)
  • EpochStats_UserWithStats (366-366)
  • EpochStats_UserWithStats (367-369)
  • UserStats (459-471)
  • UserStats (475-475)
  • UserStats (476-478)
  • GlobalStats (412-415)
  • GlobalStats (419-419)
  • GlobalStats (420-422)
  • StatsMetadata (257-261)
  • StatsMetadata (265-265)
  • StatsMetadata (266-268)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-roundtable / (roundtable) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-vulcan / (vulcan) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-bazooka-lambda / (bazooka) Build and Push Lambda
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-auxo-lambda / (auxo) Build and Push Lambda
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-bazooka-lambda / (bazooka) Build and Push Lambda
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-socks / (socks) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-roundtable / (roundtable) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-vulcan / (vulcan) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-auxo-lambda / (auxo) Build and Push Lambda
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-ender / (ender) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-comlink / (comlink) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-socks / (socks) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-comlink / (comlink) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-ender / (ender) Build and Push
  • GitHub Check: golangci-lint
  • GitHub Check: build
  • GitHub Check: container-tests
  • GitHub Check: build-and-push-testnet
  • GitHub Check: build-and-push-mainnet
  • GitHub Check: benchmark
  • GitHub Check: test-coverage-upload
  • GitHub Check: check-sample-pregenesis-up-to-date
  • GitHub Check: unit-end-to-end-and-integration
  • GitHub Check: liveness-test
  • GitHub Check: test-race
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Summary
🔇 Additional comments (9)
protocol/x/stats/keeper/keeper_test.go (3)

1061-1063: Note: TakerNotional and MakerNotional still lack underflow protection.

The comment acknowledges that TakerNotional and MakerNotional can wrap around for uint64. Looking at keeper.go lines 332-334, these fields are subtracted without clamping:

stats.TakerNotional -= removedStats.Stats.TakerNotional
stats.MakerNotional -= removedStats.Stats.MakerNotional
stats.Affiliate_30DRevenueGeneratedQuantums -= removedStats.Stats.Affiliate_30DRevenueGeneratedQuantums

If the same data inconsistency scenario occurs for these fields, they would underflow. Consider whether consistent clamping should be applied to all uint64 stats fields.


1078-1128: LGTM! Edge case test is well-structured.

The test correctly verifies exact boundary behavior where user stats equal epoch stats, ensuring the result is exactly 0 after subtraction.


1130-1221: LGTM! Multi-user test provides comprehensive coverage.

The test effectively covers three scenarios in one: normal subtraction (Alice), underflow clamping (Bob), and exact boundary (Carl). This ensures the underflow protection works correctly regardless of other users' data.

protocol/x/stats/keeper/keeper.go (1)

454-473: LGTM! New helper method is well-implemented.

The method correctly:

  • Uses prefix store with the proper key prefix
  • Properly closes the iterator with defer
  • Filters for non-zero referred volume only
  • Returns addresses as strings (matching the key type)

The full iteration is acceptable for a one-time migration operation.

protocol/app/upgrades/v9.5/constants.go (1)

1-15: LGTM! Standard upgrade constants structure.

The upgrade constants follow the established pattern with the correct version naming and empty StoreUpgrades since this upgrade doesn't modify store structure.

protocol/app/upgrades/v9.5/upgrade_test.go (2)

13-124: LGTM! Comprehensive migration test.

The test effectively covers:

  • Migration preserves existing TakerNotional/MakerNotional values (Alice, Bob)
  • Users with referred volume but no trading activity are added (Carl)
  • Users without referred volume are excluded (Dave)
  • Verifies pre-migration state has zero referred volume in epoch stats

126-169: LGTM! Empty epoch stats edge case covered.

Good test coverage for the scenario where no epoch stats exist initially, ensuring the migration creates new epoch stats correctly.

protocol/app/upgrades/v9.5/upgrade.go (2)

73-76: Potential issue: Addition instead of assignment could double-count referred volume.

Line 75 adds to existing Affiliate_30DReferredVolumeQuoteQuantums:

epochUserStats.Stats.Affiliate_30DReferredVolumeQuoteQuantums += referredVolume

However, looking at the test setup on lines 28-47 of upgrade_test.go, the initial epoch stats have no referred volume (comment: "No referred volume set yet"). If epoch stats were to already contain referred volume from normal trading activity during the epoch, this addition would result in double-counting.

Consider whether this should be an assignment instead:

-epochUserStats.Stats.Affiliate_30DReferredVolumeQuoteQuantums += referredVolume
+epochUserStats.Stats.Affiliate_30DReferredVolumeQuoteQuantums = referredVolume

Or clarify in the PR objectives if additive behavior is intentional.


108-125: LGTM! Upgrade handler follows established patterns.

The handler correctly:

  • Unwraps the SDK context with the module name
  • Logs upgrade start/completion
  • Runs the migration before standard module migrations
  • Returns the result of RunMigrations

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
protocol/app/upgrades/v9.5/upgrade.go (3)

60-76: Defensive guard for potentially nil Stats on existing epoch entries

When epochUserStats already exists (Line 62), the code assumes epochUserStats.Stats is non‑nil before incrementing Affiliate_30DReferredVolumeQuoteQuantums (Line 75). If any historical data were written with a nil Stats pointer, this would panic at upgrade time.

Even if current invariants guarantee Stats != nil, a small defensive guard keeps this migration robust against legacy/partial data:

-    } else {
-        // User already in epoch stats, add the referred volume
-        epochUserStats.Stats.Affiliate_30DReferredVolumeQuoteQuantums += referredVolume
-    }
+    } else {
+        // User already in epoch stats, add the referred volume
+        if epochUserStats.Stats == nil {
+            epochUserStats.Stats = &statstypes.UserStats{}
+        }
+        epochUserStats.Stats.Affiliate_30DReferredVolumeQuoteQuantums += referredVolume
+    }

80-86: Per‑address Info logs may be excessively verbose on large mainnet sets

Logging an Info line for every migrated address (including the running count and volume) could generate a very large number of log lines during upgrade on mainnet, which may bloat node logs and slow I/O.

Consider either:

  • lowering this to Debug (if available in your logger setup), or
  • sampling (e.g., log every Nth address), or
  • aggregating into a small number of summary logs.

116-125: “Successfully completed … Upgrade” log emitted before RunMigrations result

The handler logs "Successfully completed %s Upgrade" (Lines 123–123) before calling mm.RunMigrations (Line 125). If RunMigrations returns an error, logs will still say the upgrade completed successfully, which is misleading for operators.

Consider restructuring to log success only after migrations complete, and optionally log on error:

-    // Migrate 30d referred volume to epoch stats
-    Migrate30dReferredVolumeToEpochStats(sdkCtx, statsKeeper, epochsKeeper)
-
-    sdkCtx.Logger().Info(fmt.Sprintf("Successfully completed %s Upgrade", UpgradeName))
-
-    return mm.RunMigrations(ctx, configurator, vm)
+    // Migrate 30d referred volume to epoch stats
+    Migrate30dReferredVolumeToEpochStats(sdkCtx, statsKeeper, epochsKeeper)
+
+    newVM, err := mm.RunMigrations(ctx, configurator, vm)
+    if err != nil {
+        sdkCtx.Logger().Error(fmt.Sprintf("Error during %s Upgrade: %v", UpgradeName, err))
+        return nil, err
+    }
+
+    sdkCtx.Logger().Info(fmt.Sprintf("Successfully completed %s Upgrade", UpgradeName))
+    return newVM, nil
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb3861e and f5e243b.

📒 Files selected for processing (1)
  • protocol/app/upgrades/v9.5/upgrade.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: hwray
Repo: dydxprotocol/v4-chain PR: 2597
File: indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql:16-20
Timestamp: 2024-11-22T18:12:04.606Z
Learning: Avoid suggesting changes to deprecated functions such as `dydx_update_perpetual_v1_handler` in `indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql` if they are unchanged in the PR.
🧬 Code graph analysis (1)
protocol/app/upgrades/v9.5/upgrade.go (4)
protocol/x/stats/keeper/keeper.go (1)
  • Keeper (23-30)
protocol/mocks/Configurator.go (1)
  • Configurator (15-17)
protocol/lib/context.go (1)
  • UnwrapSDKContext (31-55)
protocol/app/upgrades/v9.5/constants.go (1)
  • UpgradeName (9-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-bazooka-lambda / (bazooka) Build and Push Lambda
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-auxo-lambda / (auxo) Build and Push Lambda
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-vulcan / (vulcan) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-roundtable / (roundtable) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-ender / (ender) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-comlink / (comlink) Build and Push
  • GitHub Check: (Mainnet) Build and Push ECS Services / call-build-and-push-ecs-service-socks / (socks) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-auxo-lambda / (auxo) Build and Push Lambda
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-vulcan / (vulcan) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-bazooka-lambda / (bazooka) Build and Push Lambda
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-socks / (socks) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-ender / (ender) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-comlink / (comlink) Build and Push
  • GitHub Check: (Public Testnet) Build and Push ECS Services / call-build-and-push-ecs-service-roundtable / (roundtable) Build and Push
  • GitHub Check: build-and-push-testnet
  • GitHub Check: benchmark
  • GitHub Check: golangci-lint
  • GitHub Check: test-coverage-upload
  • GitHub Check: unit-end-to-end-and-integration
  • GitHub Check: liveness-test
  • GitHub Check: build
  • GitHub Check: test-race
  • GitHub Check: build-and-push-mainnet
  • GitHub Check: check-sample-pregenesis-up-to-date
  • GitHub Check: container-tests
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (1)
protocol/app/upgrades/v9.5/upgrade.go (1)

89-98: Deterministic rebuild from userStatsMap looks good

Sorting keys before rebuilding epochStats.Stats (Lines 89–98) ensures deterministic ordering and avoids map‑iteration nondeterminism in state hashes. This is the right pattern for Cosmos SDK state migrations.

@jusbar23 jusbar23 merged commit 4c4f705 into main Dec 2, 2025
34 of 38 checks passed
@jusbar23 jusbar23 deleted the 9.5_upgrade branch December 2, 2025 15:44
@jusbar23
Copy link
Contributor Author

jusbar23 commented Dec 2, 2025

@mergify backport release/protocol/v9.5.x

@mergify
Copy link
Contributor

mergify bot commented Dec 2, 2025

backport release/protocol/v9.5.x

✅ Backports have been created

Details

mergify bot pushed a commit that referenced this pull request Dec 2, 2025
jusbar23 added a commit that referenced this pull request Dec 2, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jan 7, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

3 participants

Comments