Context
Flipstarter is a popular crowdfunding method on Bitcoin Cash. It uses the anyonecanpay flag so pledgers can sign an input to a partial transaction and only when all the inputs sum up to the campaign goal, the transaction becomes valid and can be broadcast on the network. Because of the limit on maximum transaction of 100kb each campaign can have maximum ~650 pledges (each input being ~148 bytes). This results in a minimum pledge amount for participating if all pledges have to go through. The current implementation calculates this minimum by dividing the outstanding sum to be raised with the number of pledges that can still fit in. Which results in a high(er) minimum at first which lowers over time. People have expressed their frustration with having to recheck for the minimum to drop to be able to contribute to a campaign.
P2SH approach
Instead of making one big transaction with a ton of inputs an alternative approach is to have a campaign fundraiser covenant contract which is restricted to accepting pledges, paying out the campaign address at completion or refunding the pledges at expiry. Then each pledge becomes a separate transaction that interacts with the campaign covenant. This approach does not run into the maximum transaction limit which means you can have arbitrarily many contributors and don’t need a relatively high minimum pledge.
Contract Demo
The approach above was known and discussed two years ago already and implemented by Tobias Ruck with spedn (but remained untested and would still run into tx limits for refund transactions). The 32bit integer restriction came up as a major reason not to go ahead with this. Now with the May 15th introspection & 64bit integers upgrade I revisited the idea again, prototyped it with cashscript and successfully demoed it on testnet. The contract makes use of the new native introspection capabilities to inspect inputs and only restrict certain outputs. (tweet on the succesful demo)
At contract expiry anyone can “roll back” the chain of contracts refunding pledgers one by one. As pointed out here by @im_uname this would improve the UX over the current approach as you would no longer have to “trigger a move away from the pledging, partially-signed output”. But also gets rid of the cancel-pledge-at-any-time concept.
The latest setup allows for campaign payouts to both P2PKH & P2SH locking scripts.
The contract currently requires the pledgers first input to have a P2PKH locking script which is reused in case of refunds. It will be future work to see if this constraint can be relaxed so as to also allow that to be a P2SH input & have P2SH refunds.
Finally, with minimal modification the smart contract approach also allows for stretch goals, meaning that a campaign payout can only happen after a certain time allowing for raising past the initial goal with extra deliverables at certain funding marks.