Skip to content

docs: document and accept the cross-contract double-funding gap (#52) - #67

Merged
chonilius merged 8 commits into
MergeFi:mainfrom
prodbycorne:docs/cross-contract-double-funding-52
Aug 17, 2026
Merged

docs: document and accept the cross-contract double-funding gap (#52)#67
chonilius merged 8 commits into
MergeFi:mainfrom
prodbycorne:docs/cross-contract-double-funding-52

Conversation

@prodbycorne

Copy link
Copy Markdown
Contributor

Summary

escrow and milestones share no registry and never call each other, so nothing on-chain stops the same issue_id from being funded via escrow::fund and simultaneously allocated a budget via milestones::allocate for some release milestone — both can independently reach release/release_issue and pay out in full for what is, off-chain, one piece of work being compensated twice.

Per the issue's own requirements, this evaluates the architectural options explicitly and makes an informed, documented decision rather than leaving the gap implicit:

  • A shared on-chain registry contract — closes the gap on-chain, but reintroduces cross-contract calls and coupling this design otherwise deliberately avoids (rejected).
  • A shared library crate with a common DataKey convention — lower coupling, but doesn't actually close the gap by itself without a cross-contract call or shared storage instance (rejected).
  • Accept the gap on-chain; mitigate at the backend layermergefi-backend already watches every fund/allocate call as the system of record for GitHub state, so it's the natural place to refuse a second commitment for an already-committed issue_id (chosen).

Changes:

  • New "Cross-contract double-funding" subsection under README's "Why three contracts instead of one," documenting the gap, the three options considered, and the decision.
  • Doc-comment cross-references in escrow::fund and milestones::allocate pointing back to that README section.
  • Roadmap entry naming the rejected on-chain registry as the fallback if backend-layer mitigation ever proves insufficient.

No contract logic changes — this is a documentation-only decision, consistent with the acceptance criteria's "if the gap is accepted... the README explicitly names this as a known, accepted limitation" path.

Closes #52

Test plan

  • cargo fmt --check — clean
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo test --workspace — 45 tests pass, no regressions
  • cargo build --target wasm32v1-none --release — succeeds

The section explained the independence tradeoff for compute_split
duplication but was silent on a bigger consequence of the same
design: escrow and milestones share no registry and never call each
other, so nothing on-chain stops the same issue_id from being funded
via both instruments at once.
…eFi#52

A fourth contract that both fund and allocate would call to claim an
issue_id closes the double-funding gap on-chain, but reintroduces the
cross-contract coupling this design otherwise deliberately avoids.
…ergeFi#52

A common DataKey convention is lower-coupling than a registry
contract, but a shared type alone doesn't close the gap — two
independently-deployed contracts still can't see each other's state
without either a cross-contract call or a shared storage instance,
either of which reintroduces the coupling this option was meant to
avoid.
…geFi#52

mergefi-backend already watches every fund/allocate call as the
system of record for GitHub state, giving it a natural, already-
required view of which issue_ids are committed — closing the gap
there needs no new contract or cross-contract coupling.
Accept the gap on-chain and push mitigation to mergefi-backend, which
already watches every fund/allocate call. Stated explicitly as a
conscious, accepted limitation of the independent-contracts design
rather than a silent gap, per issue MergeFi#52's requirements.
Points at the README's new "Cross-contract double-funding" write-up
so the accepted limitation is discoverable from the code, not only
from the README.
…allocate()

Points at the README's new "Cross-contract double-funding" write-up
so the accepted limitation is discoverable from the code, not only
from the README.
…geFi#52)

Names the rejected on-chain registry option as the fallback path if
backend-layer mitigation ever turns out to be insufficient, so the
decision recorded in "Why three contracts instead of one" isn't
treated as permanently closed.
@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

@prodbycorne is attempting to deploy a commit to the chonilius' projects Team on Vercel.

A member of the Team first needs to authorize it.

@chonilius
chonilius merged commit a190da6 into MergeFi:main Aug 17, 2026
2 of 3 checks passed
@chonilius

Copy link
Copy Markdown
Contributor

clean codes

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.

Architecture: no shared registry prevents the same issue_id from being double-funded via escrow AND milestones simultaneously

2 participants