Skip to main content
Source: Full executable TypeScript in contract/src/examples/01-campaign-all-or-nothing/. This page summarizes the flow — read the source for complete per-step code.
PrerequisitesYour platform must be enlisted — see Platform Enlistment.

The Story

Maya is a ceramic artist who sells her handmade pottery through ArtFund, a creative crowdfunding platform built on Oak Protocol. She wants to raise $5,000 to fund a new collection called “Earth & Fire” — a series of hand-thrown vases and bowls inspired by volcanic landscapes. Maya chooses the All-or-Nothing funding model. This means every dollar pledged is held in an on-chain treasury until the campaign deadline. If the campaign reaches its $5,000 goal, Maya can withdraw the funds and fulfill rewards to her backers. If the goal is not met, every backer receives a full refund automatically — no questions asked. This model builds trust with backers because their funds are protected by the smart contract. Maya cannot access the money unless the community collectively meets the target.

Multi-token support

Maya’s campaign accepts whatever ERC-20s the platform mapped to her campaign currency at creation time. Each pledge passes pledgeToken; the All-or-Nothing treasury checks CampaignInfo.isTokenAccepted. Raised totals aggregate across accepted tokens (normalized on-chain); refunds return the same token the backer used.

Role Reference

Steps

Step 1: Create Campaign

Maya creates the campaign through the CampaignInfoFactory, setting the funding goal, deadline, platform, and NFT metadata for backer receipts. The factory emits a CampaignCreated event that contains the deployed CampaignInfo address.
After the transaction is mined, the deployed CampaignInfo address can be discovered two ways. Both are shown in the source file — prefer Approach 1 when you have the receipt. Approach 1 — Decode CampaignCreated from the receipt (recommended): deterministic and works immediately, regardless of RPC indexing lag.
Approach 2 — Look up via identifierToCampaignInfo (convenience): handy when you only have the identifier and did not keep the receipt. On some RPC providers the mapping may briefly return the zero address right after the transaction, so prefer Approach 1 when the receipt is available.

Step 2: Look Up the Campaign Address

A standalone lookup is useful for any caller (not just the creator) who only has the identifier hash and wants to resolve it to the deployed CampaignInfo address — for example, a front end displaying campaign data. Maya also validates that the factory recognizes the address as a legitimate campaign.

Step 3: Review Campaign Details

Before sharing the campaign link, Maya reads back the on-chain campaign details to catch any configuration mistakes before backers start pledging.

Step 4: Deploy the Treasury

Every campaign needs a treasury — the smart contract that holds all pledged funds until the campaign outcome is decided. Maya deploys an All-or-Nothing treasury through the TreasuryFactory.

Step 5: Manage Reward Tiers

Maya sets up reward tiers. Each tier has a minimum pledge value. When a backer pledges at a tier, they receive an NFT receipt representing their pledge and chosen reward. Rewards can also be removed before backers pledge for them.

Step 6: Backer Pledges

Backers can pledge in two ways: choosing a specific reward tier with pledgeForAReward, or contributing a flat amount without a reward via pledgeWithoutAReward. In both cases the treasury transfers ERC-20 tokens and mints an NFT receipt on the CampaignInfo contract.

Step 7: Monitor Campaign Progress

Anyone can check the campaign’s progress at any time with read-only calls — no wallet required. This combines reads from both CampaignInfo (goal, deadline) and the AllOrNothing treasury (raised amount, paused/cancelled, fees, reward tiers).

Step 8: Disburse Fees

Before anyone can withdraw funds from a successful campaign, the protocol and platform fees must be disbursed first. disburseFees() has no role restriction — anyone can call it. The contract verifies internally that the deadline has passed and the goal is met.

Step 9a: Success — Withdraw Funds

After fees have been disbursed, the remaining funds are available for withdrawal. withdraw() has no role restriction — anyone can call it. The contract always sends the funds to the campaign owner, regardless of who initiates the transaction.

Step 9b: Failure — Claim Refund

If the goal is not met, every backer is entitled to a full refund. claimRefund(tokenId) has no role restriction; the contract always sends the refund to the current NFT owner, then burns the NFT. Prerequisite: the backer must approve the treasury on the CampaignInfo contract (where pledge NFTs live) before calling claimRefund.

Step 10: Pause and Unpause

If an investigation is needed, the Platform Admin can temporarily freeze all treasury activity. pauseTreasury(message) takes a bytes32 reason code emitted in the Paused event.

Step 11: Cancel the Treasury

In rare cases a campaign must be permanently shut down. Both the Platform Admin and the campaign owner can cancel. Once cancelled, no new pledges or withdrawals are allowed, but backers can still claim refunds.