docs(fundraising): group fundraising escrow design spec - #131
Open
Douglasacost wants to merge 3 commits into
Open
docs(fundraising): group fundraising escrow design spec#131Douglasacost wants to merge 3 commits into
Douglasacost wants to merge 3 commits into
Conversation
Design-only pass for the Groups feature: a group creates an objective, members deposit toward it, and the escrow resolves to exactly one of two outcomes - the beneficiary is paid, or every member takes their money back. Model is all-or-nothing with a goal latch: a member may withdraw their own deposit while the objective is below its target, and that exit closes permanently once the target is reached. Resolution is permissionless so no role, signature, or organizer cooperation can freeze member funds. Shape follows Solidity by Example's CrowdFund (the same state machine as OpenZeppelin's removed RefundEscrow), built on OpenZeppelin primitives, with Party Protocol's audit findings carried into the threat model as test cases. No contract, no tests, nothing deployed. Adds domain terms to .cspell.json.
LCOV of commit
|
…tive Factual corrections found while verifying every citation against source: - OpenZeppelin removed Escrow/ConditionalEscrow/RefundEscrow in 5.0.0, not 4.0 (vendored CHANGELOG; the contracts survived through 4.9). Corrected in three places plus the Sources entry. - Juicebox has not wound down. V4 shipped April 2025 and the protocol is live with active TVL. Its model is rejected on its own merits, not for lack of a maintainer. Party Protocol, Gitcoin Allo and Mirror had wound down as stated. - Party Protocol's review history is a 0xMacro audit plus several Code4rena engagements, not two; "the only serious audit history in this space" was overstated and is now scoped to this contract shape. - The Code4rena finalization finding locks funds until expiry rather than permanently, and is now cited as M-06 to avoid colliding with this repo's PR #127. - Solidity by Example's CrowdFund is MIT-licensed; say so instead of leaving it as an open question. Consistency and fitness: - minContribution/maxTotalContributions were listed as backend-only policy while also being on-chain fields signed into the creation authorization. They are contract-enforced on deposit and never on finalize. - Dropped IGroupFundraisingGaslessValidator from the file layout, which contradicted the conclusion that no validator hook is needed. - Fixed the stale docs/ path in the file layout. - Removed version banners, decision-log lines and references to earlier drafts so the document reads as a standalone specification.
The feature deploys new contracts only: it modifies no deployed contract, requires no token migration, and needs no change to any live paymaster. That constraint is now stated in the product framing rather than left implicit, and the open decisions are scoped to respect it. Removes the "add ERC20Permit to L2 NODL" open question. It would collapse every NODL deposit to one transaction, but it means changing a token already in production, so it is out of scope by definition. NODL deposits use the two-step approve path; the escrow still gains the single-transaction path automatically for any permit-capable token it is given. Clarifies that the erc20-fee-signer question is off-chain configuration only and not a launch blocker, since without it members simply pay their own gas. Also fixes the minContribution/maxTotalContributions contradiction that the previous commit intended to correct but did not apply: those are on-chain fields signed into the creation authorization and enforced on deposit, never on finalize.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Design-only pass for the Groups feature: a group creates an objective (a target amount and a deadline), members deposit toward it, and the escrow resolves to exactly one of two outcomes — the beneficiary is paid, or every member takes their own money back.
No contract, no tests, nothing deployed. This PR is one markdown file plus the spell-check words it needs.
Decisions recorded
Model — all-or-nothing with a goal latch. A member may withdraw their own deposit while the objective is below its target; that exit closes permanently once the target is reached. Free withdrawal right up to the deadline would let a met goal be unwound at the last second; locking from day one commits a member's money for months with no individual undo. Cutting the exit at the goal gives members a real way out while the group is still deciding, and gives the group certainty the instant it succeeds.
Resolution is permissionless. Once the goal is met or the deadline passes, anyone can finalize, and every member pulls their own funds. No role, signature, or organizer cooperation can freeze member money — this is the property the whole design is built around.
Lineage — blueprint, not dependency. Nothing in this space is importable: OpenZeppelin removed its escrow contracts in 5.0.0, Party Protocol has wound down, and no ERC standard for crowdfunding escrow was ever adopted. So:
CrowdFund(MIT), among the most widely copied crowdfunding contracts in the community and the same state machine as OpenZeppelin's removedRefundEscrow, reached independently a decade apart.SafeERC20,ReentrancyGuard,AccessControl,EIP712,SignatureChecker). This is what we actually import.Membership is backend-signed. Groups stay off-chain; single-use EIP-712 authorizations with explicit nonces gate objective creation and deposits.
Gas
§8 reflects
ERC20FeePaymaster(#127). It is destination-agnostic — the off-chainerc20-fee-signersigns(from, to, token, amount, expiry, maxFeePerGas, gasLimit)— so serving this escrow needs no change to the paymaster and no change to the escrow, only that the signer's policy covers it. Pricing happens off-chain, so there is no on-chain rate and no oracle.No feature-specific paymaster is introduced. The escrow never assumes one exists: every function works from an ordinary self-paying transaction, which is what keeps
finalize,unpledge, andrefundreachable regardless of gas infrastructure.Scope
This feature deploys new contracts only. It modifies no deployed contract, requires no token migration, and needs no change to any live paymaster — nothing currently in production is touched. Anything that would require altering an existing deployment is out of scope by definition, which is what makes this shippable independently of everything else.
Open questions in the doc
All concern the new contract only. Immutable vs. upgradeable; whether keep-what-you-raise is a real product case; protocol fee on/off; overshoot past the goal; and whether the
erc20-fee-signerpolicy should cover this escrow — the last being off-chain configuration rather than a contract change, and not a launch blocker, since without it members simply pay their own gas.