Skip to content

fix(cancel_refund): zero entry.net and decrement market totals on refund - #114

Open
esthereze wants to merge 1 commit into
SPulse-Org:mainfrom
esthereze:fix/cancel-refund-net-and-totals
Open

fix(cancel_refund): zero entry.net and decrement market totals on refund#114
esthereze wants to merge 1 commit into
SPulse-Org:mainfrom
esthereze:fix/cancel-refund-net-and-totals

Conversation

@esthereze

Copy link
Copy Markdown

Summary

Fixes the inconsistency reported in #58 where cancel_refund zeroed entry.gross but left entry.net intact, causing get_bet to still report a non-zero staked amount after a refund, and market total_yes/total_no to remain inflated.

Root cause

cancel_refund only did:

let gross = entry.gross;
entry.gross = 0; // idempotency guard

This left entry.net untouched, so:

  • get_bet returned amount: e.net (non-zero) even after the bet was refunded
  • market.total_yes/total_no were never decremented, so market totals were inconsistent with the refunded bet state

Fix

BetEntry already carries both is_yes and net, so no storage-model change is required. The fix is entirely localised to cancel_refund:

let gross = entry.gross;
let net = entry.net;
// Issue #58: zero both gross (idempotency guard) and net
entry.gross = 0;
entry.net = 0;
env.storage().persistent().set(&bet_key, &entry);

// Issue #58: decrement market totals
if entry.is_yes {
    market.total_yes = market.total_yes.saturating_sub(net);
} else {
    market.total_no = market.total_no.saturating_sub(net);
}
env.storage().persistent().set(&mkt_key, &market);

The issue description claimed this was unsolvable without a storage-model change, but that is not the case — per-bet side (is_yes) and net amount are already stored on BetEntry, making the fix purely local. saturating_sub is used defensively to prevent underflow.

Changes

  • prediction_market/src/lib.rs: cancel_refund now zeroes entry.net and decrements the appropriate market total
  • prediction_market/src/tests.rs: New test test_cancel_refund_clears_net_and_market_totals verifies both invariants

Testing

New test test_cancel_refund_clears_net_and_market_totals covers:

  1. get_bet(amount) returns 0 after cancel_refund (was non-zero before fix)
  2. market.total_yes and market.total_no are both 0 after all bettors have been refunded (were inflated before fix)
  3. get_bet_gross still returns 0 (existing idempotency guard unchanged)

Closes #58

After a successful refund, cancel_refund now:
- Zeroes entry.net alongside entry.gross (was left stale, causing get_bet
  to report a non-zero staked amount after the refund)
- Decrements market.total_yes or market.total_no by the refunded net
  amount, keeping market totals consistent with the bet ledger

BetEntry already carries both is_yes and net, so no storage-model
change is required -- the fix is purely localised to cancel_refund.
saturating_sub is used defensively to prevent any underflow edge case.

Test added: test_cancel_refund_clears_net_and_market_totals verifies
that after cancel_refund both get_bet(amount) == 0 and market totals
are decremented to 0 for a two-bettor scenario.

Closes SPulse-Org#58
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.

[MEDIUM] cancel_refund zeroes gross but leaves net intact — inconsistent bet state after refund

1 participant