Skip to content

feat: deterministic timeout-based refund finalization (SC-W6-04) - #735

Merged
Cedarich merged 3 commits into
Pulsefy:mainfrom
pharwasz:feat/sc-refund-timeout-finalization
Aug 1, 2026
Merged

Cedarich merged 3 commits into
Pulsefy:mainfrom
pharwasz:feat/sc-refund-timeout-finalization

Conversation

@pharwasz

@pharwasz pharwasz commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

SC-W6-04: Refund Timeout Finalization

Closes #565

Adds finalize_expired_escrow, a permissionless entrypoint that lets anyone finalize a refund once an escrow's timeout has passed — previously only the owner could trigger a refund, so expired escrows had no path to resolution without manual action. Also adds is_refund_eligible for keepers/indexers to check eligibility before submitting a transaction.

  • Deterministic: pure now >= expires_at check, safe to call more than once
  • Boundary conditions covered by tests (just before/at/after expiry, disputed, already-spent, non-expiring, double-finalize)
  • Emits RefundFinalized event with expires_at so indexers can reconstruct availability

cargo test: 328 passing. 4 pre-existing failures unrelated to this change (dispute voting, privacy toggle, nonce ordering), same on main, out of scope here.

@drips-wave

drips-wave Bot commented Jul 26, 2026

Copy link
Copy Markdown

@pharwasz Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Cedarich Cedarich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kindly fix failing CI

@Cedarich

Copy link
Copy Markdown
Contributor

@pharwasz

@pharwasz

Copy link
Copy Markdown
Contributor Author

Kindly fix failing CI
kindly check now

@pharwasz

sorry for the shortcomings, pls kindly approve workflow

@Cedarich

Copy link
Copy Markdown
Contributor

@pharwasz

@pharwasz

Copy link
Copy Markdown
Contributor Author

@pharwasz

Sorry about the disturbance will get it done

@Cedarich

Copy link
Copy Markdown
Contributor

@pharwasz

@pharwasz

Copy link
Copy Markdown
Contributor Author

While working on this branch, I found 4 pre-existing test failures unrelated to the feature/logic changes here. These were issues in the test code itself, not the contract:

  1. test_assert_helpers_disputed_and_refunded — used TestContext::new(), which doesn't initialize the contract with an admin. Dispute resolution requires the arbiter to hold the global Arbiter role, so this was failing with NotArbiter (#312). Fixed by switching to TestContext::with_admin().

  2. test_demo_dispute_flow_under_10_lines — same root cause as above, same fix.

  3. test_demo_privacy_toggle_under_10_lines — was failing with Unauthorized (#200) due to the same missing initialization pattern. Fixed and added a comment clarifying the auth requirement for future readers.

  4. test_deposit_with_commitment_duplicate_fails — expected CommitmentAlreadyExists (#303), but the contract actually returns NonceAlreadyUsed (#500) first, since nonce replay protection runs before the commitment-existence check. Both errors correctly prevent the duplicate deposit — the test's expectation was just out of date with the contract's check ordering. Updated the assertion and added a comment explaining why.

No contract/business logic was changed — all fixes are confined to coverage_test.rs and bring the test expectations in line with existing, correct contract behavior. All 332 tests pass after these fixes.

Closes Pulsefy#565

Adds finalize_expired_escrow, a permissionless entrypoint that lets
anyone finalize a refund once an escrow's timeout has passed --
previously only the owner could trigger a refund, so expired escrows
had no path to resolution without manual action. Also adds
is_refund_eligible for keepers/indexers to check eligibility before
submitting a transaction.

- Deterministic: pure now >= expires_at check, safe to call more than once
- Boundary conditions covered by tests (just before/at/after expiry,
  disputed, already-spent, non-expiring, double-finalize)
- Emits RefundFinalized event with expires_at so indexers can
  reconstruct availability
@pharwasz
pharwasz force-pushed the feat/sc-refund-timeout-finalization branch from 654c559 to 1a365f4 Compare July 30, 2026 17:30
@Cedarich

Copy link
Copy Markdown
Contributor

@pharwasz

@pharwasz

Copy link
Copy Markdown
Contributor Author

@Cedarich test_event_schema_catalog_locks_canonical_topics_and_payloads (test.rs:359) fails on a clean merge of this branch into current main, with no changes of mine involved, I verified by merging feat/sc-refund-timeout-finalization directly into upstream/main locally. The assertion expects 26 schemas but the catalog is at 25. It looks like recent additions to main (oracle price events, EmergencyModeActivated, FeeConfigChanged, PlatformWalletChanged) added new event schemas without bumping this hardcoded count. Unrelated to SC-W6-04.

@pharwasz

Copy link
Copy Markdown
Contributor Author

@Cedarich

@Cedarich

Copy link
Copy Markdown
Contributor

@pharwasz

@pharwasz

pharwasz commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@Cedarich Can you confirm this is a known/tracked issue on main? If not I’m happy to open a separate PR bumping the count, just don’t want to bundle an unrelated fix into this one. Let me know how you’d like to proceed so I can get this merged.

@Cedarich

Cedarich commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@pharwasz
Thanks for the change — this looks useful. One problem I noticed: there are contradictory assertions in the tests that will always fail CI:

assert_eq!(EVENT_SCHEMAS.len(), 25);
assert_eq!(EVENT_SCHEMAS.len(), 26);

It looks like the first assertion (expecting 25) was left behind when the new event was added. Please either remove the spurious assert_eq!(EVENT_SCHEMAS.len(), 25); or update the expected value(s) so they consistently reflect the current number of schemas (after adding RefundFinalized).

Merging main introduced duplicate/stale assert_eq! lines for
EVENT_SCHEMAS.len() (25 and 26), left over from a merge conflict.
The actual schema count is 27 after main's oracle/emergency-mode/
fee-config event additions. Consolidated to a single correct
assertion.

All 353 tests pass, cargo fmt --all -- --check is clean.
@pharwasz

pharwasz commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@pharwasz Thanks for the change — this looks useful. One problem I noticed: there are contradictory assertions in the tests that will always fail CI:

assert_eq!(EVENT_SCHEMAS.len(), 25);
assert_eq!(EVENT_SCHEMAS.len(), 26);

It looks like the first assertion (expecting 25) was left behind when the new event was added. Please either remove the spurious assert_eq!(EVENT_SCHEMAS.len(), 25); or update the expected value(s) so they consistently reflect the current number of schemas (after adding RefundFinalized).

Fixed, the duplicate/contradictory EVENT_SCHEMAS.len() assertions were leftover from the merge conflict resolution. Consolidated to a single assert_eq!(EVENT_SCHEMAS.len(), 27) matching the actual post-merge schema count. All 353 tests pass locally and cargo fmt --check is clean. Ready for another look whenever you get a chance 🙏

@Cedarich Cedarich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

Thank you @pharwasz for the contribution 👍

@Cedarich
Cedarich merged commit 1b35029 into Pulsefy:main Aug 1, 2026
6 checks passed
@pharwasz

pharwasz commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

LGTM!
Thank you @pharwasz for the contribution

👍thanks for the opportunity @Cedarich

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.

SC-W6-04: Refund Timeout Finalization

2 participants