You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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
Background
This is the piece that actually closes the loop between the two contracts.
dispute-resolution::resolve_disputeandcampaign-escrow::resolve_dispute_payoutare both stilltodo!(), and their doc comments already point at each other as the intended integration:Note:
campaign-escrowalready 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 (seedocs/ARCHITECTURE.md), not replace each other. Worth naming this function something other thanresolve_dispute_payoutcallers-side if the tworesolve_disputenames (one per contract) get confusing in practice, but that's a bikeshed, not a blocker.Expected behaviour
dispute-resolution::resolve_dispute:arbiter.require_auth(), must matchdispute.arbiter(requires feat: implement dispute-resolution::assign_arbiter() #41, arbiter assignment, to land first)DisputeStatus::UnderReviewdispute.outcome = outcome,status = Resolved,resolved_at = Some(env.ledger().timestamp())campaign_escrow::Client::resolve_dispute_payout(campaign_id, creator, creator_bps)on the configuredescrow_contract, translatingDisputeOutcome→ thecreator_bps: i128parameter (CreatorFavored→ 10_000,BusinessFavored→ 0,Split(bps)→bps)events::DisputeResolvedcampaign-escrow::resolve_dispute_payout:dispute_contractaddress (storage::get_dispute_contract) — this is the actual authentication mechanism for a trusted cross-contract call in Soroban, since there's norequire_auth-able "caller" identity to check the way there is for a user address. Verify viaenv.current_contract_address()/invoker checks per the existing TODO comment on this function.payout_amountpercreator_bps(this is essentially the same fee/split math already implemented inresolve_disputefrom 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)freeze_for_disputeissue)Files
contracts/dispute-resolution/src/lib.rs—resolve_disputecontracts/campaign-escrow/src/lib.rs—resolve_dispute_payoutAcceptance criteria
dispute-resolution::resolve_disputetransitions the dispute toResolvedand calls intocampaign-escrowcampaign-escrow::resolve_dispute_payoutrejects any caller other than the configured dispute contractcreator_bpsexactly (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 #30dispute-resolution, verify balances moved correctly oncampaign-escrow(this is also good input for the cross-contract integration test issue)resolve_dispute_payoutfrom a non-dispute-contract address is rejected