Skip to content

Expand test coverage for escrow splits, postponement, and resale edge cases - #155

Merged
DioChuks merged 2 commits into
BuidlZone-Labs:mainfrom
Depo-dev:test/escrow-splits-postponement-resale-coverage
Jul 29, 2026
Merged

Expand test coverage for escrow splits, postponement, and resale edge cases#155
DioChuks merged 2 commits into
BuidlZone-Labs:mainfrom
Depo-dev:test/escrow-splits-postponement-resale-coverage

Conversation

@Depo-dev

@Depo-dev Depo-dev commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Closes #145

Summary

Adds automated test coverage for four high-risk edge cases identified in #145:

  • Multi-token revenue splits with mid-event co-host flagging — flags a co-host before event completion/settlement and verifies the flag still blocks withdrawal after settlement; verifies split settlement only touches the event's payout-token revenue, leaving other-token revenue untouched.
  • Postponement refund boundary — exercises choice_deadline_ledger exactly at the boundary (<= still open) and one ledger past it (closed).
  • Resale royalty exceeding proceedssync_event_config on the payments contract has no cap on resale_royalty_bps (unlike the event contract's front door, which caps it at 2000 bps). This test documents current behavior when royalty bps alone exceeds the resale price: seller_proceeds goes negative, the > 0 guard means the seller receives nothing, and the buyer's payment is fully retained by the contract while ownership still transfers.
  • Escrow release after multiple delay extensions — verifies extend_withdrawal_delay calls are cumulative and correctly gate withdraw_split.

Test plan

  • cargo test -p payments-contract — 21/21 passed
  • cargo test -p event-contract — 17/17 passed

Summary by CodeRabbit

  • Tests
    • Added coverage confirming postponement refunds succeed at the exact deadline and fail immediately afterward.
    • Added coverage for resale royalties exceeding available proceeds, including ticket transfer and unpaid seller outcomes.
    • Added tests for co-host withdrawal restrictions, payout-token-only revenue splitting, and cumulative admin withdrawal delays.

…ale royalty edge cases

Covers co-host flagging mid-event before settlement, multi-token revenue
isolation during splits, escrow release after repeated admin delay
extensions, the choice_deadline_ledger boundary for postponement refunds,
and resale royalty configurations that exceed total proceeds.
@drips-wave

drips-wave Bot commented Jul 28, 2026

Copy link
Copy Markdown

@Depo-dev 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

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Depo-dev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 73fad8b1-17c5-4b34-aefc-a13dae9b7cdc

📥 Commits

Reviewing files that changed from the base of the PR and between 6d520c8 and 52f7172.

📒 Files selected for processing (1)
  • contracts/payments/src/revenue_split_test.rs
📝 Walkthrough

Walkthrough

Adds integration and unit-test coverage for postponement refund boundaries, excessive resale royalties, co-host flagging, multi-token settlement, and cumulative withdrawal-delay extensions.

Changes

Contract edge-case coverage

Layer / File(s) Summary
Event postponement and resale edge cases
contracts/event/src/integration_tests.rs
Tests refund success at the exact postponement deadline, rejection one ledger later, and resale ownership transfer when excessive royalties leave seller proceeds at zero.
Revenue split settlement behavior
contracts/payments/src/revenue_split_test.rs
Tests persistent co-host withdrawal blocking, payout-token-only settlement, and cumulative withdrawal-delay extensions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: codeze-us, josephchimebuka

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has the issue link and a summary, but it omits most required template sections like change type, impact analysis, and acceptance criteria sign-off. Add the missing template sections, especially What this PR does, change type, test coverage, acceptance criteria, and any relevant impact/checklist details.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: expanded test coverage for escrow splits, postponement, and resale edge cases.
Linked Issues check ✅ Passed The tests cover all four #145 edge cases: active co-host split withdrawal, postponement refund boundary, over-royalty resale, and cumulative withdrawal-delay extensions.
Out of Scope Changes check ✅ Passed The changes stay within the two test files named in #145 and add no unrelated behavior or public API changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (3)
contracts/payments/src/revenue_split_test.rs (1)

752-802: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an exact-boundary assertion at the computed unlock ledger (26280).

The test proves extensions accumulate (20_000 fails, 26_281 succeeds) but never checks ledger 26_280 itself, so an off-by-one in the cumulative extension math wouldn't be caught. The sibling postponement tests in contracts/event/src/integration_tests.rs test both "exactly at deadline" and "one past deadline" — worth mirroring that precision here.

♻️ Suggested addition
     env.ledger().with_mut(|li| li.sequence_number = 20_000);
     assert_eq!(
         client.try_withdraw_split(&cohost, &event_id).err(),
         Some(Ok(PaymentError::EscrowNotExpired))
     );
 
+    // Exactly at the computed unlock ledger.
+    env.ledger().with_mut(|li| li.sequence_number = 26_280);
+    // assert on expected pass/fail behavior here, matching the contract's boundary convention.
+
     env.ledger().with_mut(|li| li.sequence_number = 26_281);
     client.withdraw_split(&cohost, &event_id);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/payments/src/revenue_split_test.rs` around lines 752 - 802, Update
test_withdraw_split_respects_admin_delay_extension_after_multiple_extensions to
assert that withdrawal at ledger 26,280 still returns
PaymentError::EscrowNotExpired, then advance to ledger 26,281 and preserve the
successful withdrawal assertion.
contracts/event/src/integration_tests.rs (2)

1026-1070: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider asserting no side effects on the failure path.

The test correctly validates the error variant at deadline+1, but doesn't confirm balances/payment status remain untouched after the rejected call — cheap to add and rules out partial-state mutation bugs.

♻️ Suggested addition
     let res = payments_client.try_request_postponement_refund(&attendee, &t);
     assert_eq!(
         res.err(),
         Some(Ok(
             payments_contract::PaymentError::PostponementWindowClosed
         ))
     );
+    assert_eq!(_token_client.balance(&attendee), 0);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/event/src/integration_tests.rs` around lines 1026 - 1070, Extend
test_postponement_refund_one_ledger_past_deadline_fails to capture the
attendee’s token balance and payment status before
try_request_postponement_refund, then assert both remain unchanged after the
PostponementWindowClosed error. Use the existing balance and payment-status
accessors available through payments_client or the token client.

1080-1138: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicates setup_linked's cross-contract wiring instead of reusing it.

This block re-implements the same event/ticket/payments registration and initialization already in setup_linked (lines 326-377), just to add two extra calls. Consider extending setup_linked (or adding a small wrapper) to include ticket_client.set_payments_contract / payments_client.set_ticket_contract so resale-oriented tests can reuse it.

♻️ Suggested refactor direction
 fn setup_linked(
     env: &Env,
 ) -> ( /* ... */ ) {
     // ... existing wiring ...
+    ticket_client.set_payments_contract(&organizer, &payments_contract_id);
+    payments_client.set_ticket_contract(&organizer, &ticket_contract_id);
     (event_client, payments_client, ticket_client, token_client, token_admin_client, token_address, organizer, payments_contract_id)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/event/src/integration_tests.rs` around lines 1080 - 1138, Refactor
the resale test setup to reuse setup_linked instead of duplicating contract
registration and cross-contract initialization. Extend setup_linked, or add a
focused wrapper around it, to perform ticket_client.set_payments_contract and
payments_client.set_ticket_contract, then update this test to use that shared
setup while preserving its event-specific configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@contracts/event/src/integration_tests.rs`:
- Around line 1026-1070: Extend
test_postponement_refund_one_ledger_past_deadline_fails to capture the
attendee’s token balance and payment status before
try_request_postponement_refund, then assert both remain unchanged after the
PostponementWindowClosed error. Use the existing balance and payment-status
accessors available through payments_client or the token client.
- Around line 1080-1138: Refactor the resale test setup to reuse setup_linked
instead of duplicating contract registration and cross-contract initialization.
Extend setup_linked, or add a focused wrapper around it, to perform
ticket_client.set_payments_contract and payments_client.set_ticket_contract,
then update this test to use that shared setup while preserving its
event-specific configuration.

In `@contracts/payments/src/revenue_split_test.rs`:
- Around line 752-802: Update
test_withdraw_split_respects_admin_delay_extension_after_multiple_extensions to
assert that withdrawal at ledger 26,280 still returns
PaymentError::EscrowNotExpired, then advance to ledger 26,281 and preserve the
successful withdrawal assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 41b4ab9e-57b2-4684-953b-6e475c88c447

📥 Commits

Reviewing files that changed from the base of the PR and between 966837f and 6d520c8.

📒 Files selected for processing (2)
  • contracts/event/src/integration_tests.rs
  • contracts/payments/src/revenue_split_test.rs

@DioChuks
DioChuks merged commit ce461e2 into BuidlZone-Labs:main Jul 29, 2026
5 checks passed
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.

Expand Test Suite Coverage for Escrow Splits, Postponement Edge Cases, and Multi-Token Settlements

2 participants