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.
validateServiceis 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
createAgreementtransaction (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 ascancelAgreementare authorized exclusively to the backend signer, not to end-user wallets. - Funder (payer): The wallet that deposits funds via
fundAgreement. ONLY the funder can callunlockFundsorunlockAfterCompletionTimeout. - Partners / Providers: Each participant added to the agreement. ONLY a partner can call
acceptAgreementfor theirpartnerId, and partners sharevalidateServicepermissions 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 viaServiceState.CalledMediator.
3. Agreement Lifecycle (Authoritative)¶
Phase 1 — Acceptance¶
- Each partner calls
acceptAgreement(agreementId, partnerId)once their wallet is ready. - The contract emits
PartnerAcceptedfor every acceptance. - 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.ServiceStateencoding:0=Pending1=Validated2=Declined3=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)andnumApprovedServices == validatorCount, the same transaction automatically: - Pays each approved partner their allocation via ERC‑20 transfers.
- Sets
fundState = DistributedandserviceState = Validated. - Emits
AgreementValidated. unlockFundsis not involved in this path.
All Validators Decline¶
- When the final validator submits
ServiceState.Declined (2)andnumDeclinedServices == validatorCount, the same transaction: - Refunds the funder’s wallet in full (protocol fees remain collected).
- Sets
fundState = UnlockedFundandserviceState = 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 emitsAgreementMediated. - 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 = UnlockedFundbefore emittingAgreementCancelled. - 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) |