Skip to content

feat: wire dispute-resolution::resolve_dispute() to campaign-escrow::resolve_dispute_payout() #42

Description

@JamesVictor-O

Background

This is the piece that actually closes the loop between the two contracts. dispute-resolution::resolve_dispute and campaign-escrow::resolve_dispute_payout are both still todo!(), and their doc comments already point at each other as the intended integration:

resolve_dispute ... resolves a dispute with a final outcome, then calls back into campaign_escrow::resolve_dispute_payout to release/refund the frozen funds accordingly.

Note: campaign-escrow already has an admin-only, single-contract dispute settlement path (resolve_dispute, added in #30) that works today without any of this. This issue is about the separate, arbiter-resolved, cross-contract path — the two are meant to coexist (see docs/ARCHITECTURE.md), not replace each other. Worth naming this function something other than resolve_dispute_payout callers-side if the two resolve_dispute names (one per contract) get confusing in practice, but that's a bikeshed, not a blocker.

Expected behaviour

dispute-resolution::resolve_dispute:

pub fn resolve_dispute(env: Env, arbiter: Address, dispute_id: DisputeId, outcome: DisputeOutcome) -> Result<(), Error>
  • arbiter.require_auth(), must match dispute.arbiter (requires feat: implement dispute-resolution::assign_arbiter() #41, arbiter assignment, to land first)
  • Dispute must be DisputeStatus::UnderReview
  • Set dispute.outcome = outcome, status = Resolved, resolved_at = Some(env.ledger().timestamp())
  • Call campaign_escrow::Client::resolve_dispute_payout(campaign_id, creator, creator_bps) on the configured escrow_contract, translating DisputeOutcome → the creator_bps: i128 parameter (CreatorFavored → 10_000, BusinessFavored → 0, Split(bps)bps)
  • Emit events::DisputeResolved

campaign-escrow::resolve_dispute_payout:

pub fn resolve_dispute_payout(env: Env, campaign_id: CampaignId, creator: Address, creator_bps: i128) -> Result<(), Error>
  • Must only be callable by the configured dispute_contract address (storage::get_dispute_contract) — this is the actual authentication mechanism for a trusted cross-contract call in Soroban, since there's no require_auth-able "caller" identity to check the way there is for a user address. Verify via env.current_contract_address()/invoker checks per the existing TODO comment on this function.
  • Splits the frozen application's payout_amount per creator_bps (this is essentially the same fee/split math already implemented in resolve_dispute from Title: feat: add resolve_dispute admin function with DisputeResolution enum and Disputed status #30 — consider factoring the shared logic into a private helper both functions call, rather than duplicating it)
  • Unfreezes the application (clears the flag from the freeze_for_dispute issue)

Files

  • contracts/dispute-resolution/src/lib.rsresolve_dispute
  • contracts/campaign-escrow/src/lib.rsresolve_dispute_payout

Acceptance criteria

  • dispute-resolution::resolve_dispute transitions the dispute to Resolved and calls into campaign-escrow
  • campaign-escrow::resolve_dispute_payout rejects any caller other than the configured dispute contract
  • Fund split matches creator_bps exactly (0, 10_000, and a fractional split), consistent with the fee-on-creator's-share-only rule already established in Title: feat: add resolve_dispute admin function with DisputeResolution enum and Disputed status #30
  • Test: full round trip — raise → assign → resolve on dispute-resolution, verify balances moved correctly on campaign-escrow (this is also good input for the cross-contract integration test issue)
  • Test: a direct call to resolve_dispute_payout from a non-dispute-contract address is rejected

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions