Skip to content

Using the Escrow After Agreement Creation

1. High-Level Overview

  • The DShare smart contract is the single source of truth for every state change after agreement creation.
  • Fund movements happen inside contract functions. When conditions are met, transfers execute immediately within the transaction that satisfied those conditions.
  • validateService is the core lifecycle function: it records participant decisions and automatically routes funds to partners, funders, or the mediator depending on the outcome.

2. Roles & On-Chain Permissions

  • Creator (on-chain): The creator address recorded on-chain is the wallet that submits the createAgreement transaction (msg.sender). In the current architecture, this is a backend-controlled signer wallet acting on behalf of the user who initiated agreement creation via the API. As a result, creator-only actions such as cancelAgreement are authorized exclusively to the backend signer, not to end-user wallets.
  • Funder (payer): The wallet that deposits funds via fundAgreement. ONLY the funder can call unlockFunds or unlockAfterCompletionTimeout.
  • Partners / Providers: Each participant added to the agreement. ONLY a partner can call acceptAgreement for their partnerId, and partners share validateService permissions with the funder.
  • Mediator: Optional address set when the agreement is created. ONLY the mediator can call mediatorApprove. Any validator (partner or funder) can escalate to the mediator via ServiceState.CalledMediator.

3. Agreement Lifecycle (Authoritative)

Phase 1 — Acceptance

  1. Each partner calls acceptAgreement(agreementId, partnerId) once their wallet is ready.
  2. The contract emits PartnerAccepted for every acceptance.
  3. When all partners have accepted and the funder has already locked funds, DShare automatically emits AgreementApproved. No funds move during acceptance; balances remain locked in escrow.

Phase 2 — Service Validation (CORE LOGIC)

  • validateService(agreementId, ServiceState state) can be called by any approved partner or the funder.
  • ServiceState encoding:
  • 0 = Pending
  • 1 = Validated
  • 2 = Declined
  • 3 = CalledMediator
  • Every call updates the caller’s service state and the global counters. DShare moves funds inside this function as soon as the relevant condition is satisfied.

All Validators Approve

  • When the final validator submits ServiceState.Validated (1) and numApprovedServices == validatorCount, the same transaction automatically:
  • Pays each approved partner their allocation via ERC‑20 transfers.
  • Sets fundState = Distributed and serviceState = Validated.
  • Emits AgreementValidated.
  • unlockFunds is not involved in this path.

All Validators Decline

  • When the final validator submits ServiceState.Declined (2) and numDeclinedServices == validatorCount, the same transaction:
  • Refunds the funder’s wallet in full (protocol fees remain collected).
  • Sets fundState = UnlockedFund and serviceState = Cancelled.
  • Emits UnlockFunds(agreementId, funderAddress) as confirmation.
  • Again, no separate unlock call exists or is required.

Arbitration Escalation

  • Any validator can pass ServiceState.CalledMediator (3) provided a mediator address was set.
  • The transaction immediately transfers the entire net amount to the mediator, sets serviceState = Mediation, and emits AgreementMediated.
  • This bypasses unlock logic entirely and is irreversible. If a validator escalates, funds leave escrow within that call.

4. Fallback & Emergency Paths

These functions do not run during the normal lifecycle. They exist for exceptional cases and always require a manual transaction from the funder.

unlockFunds

  • Callable only by the funder while globalState == Pending, serviceState == Pending, and funds are still locked.
  • Purpose: early exit before the agreement is approved. The call refunds the funder immediately and emits UnlockFunds.

unlockAfterCompletionTimeout

  • Callable only by the funder after the completion deadline has passed, provided the agreement is not cancelled, not in mediation, and funds remain locked.
  • Purpose: deadline-based manual refund if validators never finish service validation. Emits UnlockFundsAfterTimeout.

5. Cancellation

  • cancelAgreement(agreementId) can be executed only by the creator while the agreement is pending.
  • If escrow funds were locked, the same transaction refunds the funder and sets fundState = UnlockedFund before emitting AgreementCancelled.
  • No automatic cancellation exists; the creator must submit the transaction.

6. Event-Driven Integration

Integrators MUST subscribe to events to track the escrow without polling: - PartnerAccepted - AgreementApproved - AgreementValidated - AgreementMediated - UnlockFunds - FundsUnlocked (ERC-20 payout confirmation when applicable) - UnlockFundsAfterTimeout

Events are emitted in the exact transaction that moved funds or changed state, making them the authoritative feed for dashboards, accounting, and alerts.

7. Transaction Signing Model

The DShare escrow protocol is wallet-agnostic. Any Ethereum-compatible wallet (EOA, smart wallet, MPC, custodial service, etc.) can interact with the contract, provided the wallet address matches the role stored on-chain (creator, funder, partner, or mediator).

The protocol does not inspect wallet provenance or custody model. It relies exclusively on msg.sender equality checks for authorization.

How transactions are signed or managed (e.g., browser wallets, hardware wallets, custodial services) is outside the scope of this protocol and does not affect on-chain behavior.

8. Summary Table

Scenario Function that moves funds Triggering role Automatic or explicit
All validators approve validateService (final call with ServiceState.Validated) Approving validator (partner or funder) Automatic (inside the call)
All validators decline validateService (final call with ServiceState.Declined) Declining validator (partner or funder) Automatic refund
Arbitration escalation validateService with ServiceState.CalledMediator Any validator Automatic mediator payout
Early exit before approval unlockFunds Funder only Explicit transaction
Missed completion deadline unlockAfterCompletionTimeout Funder only Explicit transaction
Creator cancels pending agreement cancelAgreement Creator only Explicit transaction (includes refund if funded)