Skip to content

feat(contract): implement consent-based escrow migration between deployments - #222

Open
omoh5 wants to merge 13 commits into
DocForum:mainfrom
omoh5:feat/migrate-open-escrows-from-an-old-deployment-to-a
Open

omoh5 wants to merge 13 commits into
DocForum:mainfrom
omoh5:feat/migrate-open-escrows-from-an-old-deployment-to-a

Conversation

@omoh5

@omoh5 omoh5 commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Closes #117

Summary

Implements a consent-based migration protocol that allows open escrows to move securely between supported Soroban contract deployments.

The migration requires authorization from both the payer and releaser, verifies trusted source deployments, and ensures escrow funds and records move atomically.

Changes

  • Added an Architecture Decision Record describing the migration protocol.
  • Implemented export_to on the source escrow contract.
  • Implemented import_from on the destination contract.
  • Added payer and releaser authorization checks.
  • Added trusted-source deployment verification.
  • Added replay protection and duplicate migration prevention.
  • Added atomic funds and escrow state migration.
  • Added integration tests using two contract instances.
  • Updated integrator documentation and deployment limitations.
  • Updated Phase E5 in ROADMAP.md.

Security Design

Authorization: Both payer and releaser must approve migration.

Trusted source verification: [Describe actual allowlist and authenticated invocation mechanism.]

Atomicity: [Explain how contract state changes and token transfers roll back together.]

Replay prevention: [Describe the migration identity and duplicate detection.]

Escrow lifecycle: [Explain how the source escrow becomes non-spendable after migration.]

Compatibility

Existing immutable testnet deployments without an export function cannot use this protocol.

Integrators must continue tracking those deployments and settle their escrows through existing release or refund paths.

Testing

Integration tests cover:

  • Successful migration between two contract instances.
  • Missing payer consent.
  • Missing releaser consent.
  • Unrecognized source contracts.
  • Forged import attempts.
  • Duplicate migrations.
  • Destination failure and rollback.
  • Ineligible escrow states.
  • Escrow ID collisions.
  • Token balance integrity.

Verification

From contracts/escrow/:

  • cargo test — [Actual result]
  • cargo build --target wasm32v1-none --release — [Actual result]

If SDK changes were required:

  • npm run typecheck — [Actual result]
  • npm run build — [Actual result]
  • npm run test:integration — [Actual result, if applicable]

Test output: [Paste actual output or a relevant excerpt.]

Documentation

  • Added migration protocol ADR: [Filename].
  • Updated README with integrator guidance.
  • Updated applicable architecture documentation.
  • Updated Phase E5 roadmap status and changelog entry.

Scope

This PR is limited to consent-based escrow migration, security validation, required contract tests, ADR documentation, and related integration guidance.

It does not retroactively enable migration for existing immutable deployments.

@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@omoh5 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

@github-actions github-actions Bot added the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 21, 2026
@github-actions

Copy link
Copy Markdown

@omoh5 This PR now has merge conflicts with main, most likely because #152 (feat(contract): payer cancellation window before the payee accepts) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run:

Reproducible WASM across checkout paths, SDK bindings match contract WASM, Soroban contract (test + wasm build)

error[E0425]: cannot find type `MigrationKey` in this scope
error[E0422]: cannot find struct, variant or union type `MigrationData` in this scope
error[E0422]: cannot find struct, variant or union type `MigrationKey` in this scope
error[E0425]: cannot find type `MigrationData` in this scope
error[E0599]: no variant, associated function, or constant named `MigrationNotEligible` found for enum `Error` in the current scope
error[E0599]: no variant, associated function, or constant named `MigrationFailed` found for enum `Error` in the current scope
error[E0599]: no variant, associated function, or constant named `Migrated` found for enum `EscrowStatus` in the current scope
error[E0599]: no variant, associated function, or constant named `UnapprovedSource` found for enum `Error` in the current scope

MigrationKey, MigrationData, the Migrated status and the new Error variants are used but not defined. The type and enum additions were probably dropped while resolving the rebase. Re-add them (Error codes must stay append-only), then regenerate the bindings.

This PR also conflicts with main again, so please rebase first, then fix the above.

@github-actions github-actions Bot removed the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 22, 2026
@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run:

SDK bindings match contract WASM, Reproducible WASM across checkout paths, Soroban contract (test + wasm build)

error[E0425]: cannot find type `MigrationKey` in this scope
error[E0422]: cannot find struct, variant or union type `MigrationData` in this scope
error[E0422]: cannot find struct, variant or union type `MigrationKey` in this scope
error[E0425]: cannot find type `MigrationData` in this scope
error[E0599]: no variant, associated function, or constant named `MigrationNotEligible` found for enum `Error` in the current scope
error[E0599]: no variant, associated function, or constant named `MigrationFailed` found for enum `Error` in the current scope
error[E0599]: no variant, associated function, or constant named `Migrated` found for enum `EscrowStatus` in the current scope
error[E0599]: no variant, associated function, or constant named `UnapprovedSource` found for enum `Error` in the current scope

These are the same errors as before: MigrationKey, MigrationData and the migration Error variants still aren't defined. See my earlier comment.

@github-actions github-actions Bot added the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 23, 2026
@github-actions

Copy link
Copy Markdown

@omoh5 This PR now has merge conflicts with main, most likely because #257 (feat(contract): pooled escrows funded by multiple payers with pro-rata refunds) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@github-actions github-actions Bot removed the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 23, 2026
@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run (Soroban contract (test + wasm build), also SDK bindings and reproducible WASM):

error[E0063]: missing field `release_not_before` in initializer of `EscrowData`
error[E0422]: cannot find struct, variant or union type `MigrationData` / `MigrationKey`
error[E0599]: no variant `AlreadyMigrated` / `InvalidMigration` / `MigrationFailed` on `Error`
error[E0599]: no variant `ApprovedSources` / `Imported` on `DataKey`
error[E0599]: no variant `Migrated` on `EscrowStatus`

The migration types and variants still aren't defined anywhere on this branch, and EscrowData on main now has a release_not_before field that your initializer needs to set. Add the missing definitions (error codes are append-only), run cargo build and cargo test in contracts/escrow, then regenerate the bindings.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 CI is failing in the contract build (Soroban test, SDK bindings and reproducible-WASM jobs all hit the same compile errors):

error[E0422]: cannot find struct, variant or union type `MigrationData` in this scope
error[E0422]: cannot find struct, variant or union type `MigrationKey` in this scope
error[E0599]: no variant ... named `ApprovedSources` found for enum `DataKey`
error[E0599]: no variant ... named `MigrationNotEligible` found for enum `Error`
error[E0599]: no variant ... named `Migrated` found for enum `EscrowStatus`
error[E0599]: no variant ... named `Imported` found for enum `DataKey`

The migration code is there, but the type, enum and DataKey additions it depends on were lost (likely while merging main). Please restore them, run cargo test in contracts/escrow, and push.

@github-actions github-actions Bot added the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 27, 2026
@github-actions

Copy link
Copy Markdown

@omoh5 This PR now has merge conflicts with main, most likely because #254 (feat(contract): batch release and refund for fast settlement of many escrows) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-escrow.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 Heads-up: #268 just changed how contract PRs work in this repo. Your PR changes contracts/escrow/src/lib.rs, so CI's new "Contract changes use a fragment, not a version bump" step will fail it until you make these changes (details in contract-changes.d/README.md):

  1. Don't edit CONTRACT_VERSION when you merge main (currently 2.3.0). Keep main's line as it is.

  2. Add a fragment, e.g. contract-changes.d/<issue>-feat-contract-implement-consent-based-es.md:

    bump: minor
    ---
    Issue #NN: one-paragraph summary of the contract change.

    Use patch for a behaviour fix with no interface change, minor for new entry points, arguments, events or errors, and major for breaking changes.

  3. If you add any new Error variants, give them provisional codes (issue number × 100 + n, e.g. NN00) and never renumber existing ones.

This should also make your next merge from main much easier: the version line was the one thing every contract PR conflicted on.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@omoh5 The new contract check (#268, see my earlier comment) fails this PR: contracts/escrow/src/lib.rs changed, but no fragment was added under contract-changes.d/. Add contract-changes.d/<issue>-<slug>.md (bump: minor, ---, one-paragraph summary). Also regenerate sdk/src/generated/contract-client.ts with stellar CLI 28.1.0, because the "SDK bindings match contract WASM" job reports it out of date. Don't edit CONTRACT_VERSION. Then push.

@github-actions github-actions Bot removed the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 29, 2026
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.

[Phase E5] Migrate open escrows from an old deployment to a new one with both parties' consent

2 participants