ethereum-kickstarter-app: The Micro-DAO Hiding Inside a Kickstarter Clone
A compact Ethereum crowdfunding app that replaces trust in a middleman with contract-enforced voting, factory-deployed campaigns, and a web stack that still works for non-wallet users.
- The repo turns crowdfunding into a governance problem by making contributors into approvers who can unlock spending.
- A factory contract standardizes campaign creation, which is as much a trust decision as a code reuse decision.
- The frontend matters because the app is built to behave like a normal website even when the blockchain layer is absent.
- The project is small, but it teaches the core EVM lesson: every state change should be designed around gas, storage, and verification.
This repo is not really about copying Kickstarter on Ethereum. It is about a sharper question: who gets to say yes when money moves? In this design, contributors are not passive backers. They become the voting body that decides whether campaign funds can be spent.
What if every backer became a voter?
That is the app's twist. A contribution does more than transfer ETH. It grants approver status, which means the same people who fund a campaign can later block or authorize its spending requests.
The result feels closer to a micro-DAO than a fundraising page. The contract enforces the rule mechanically, so the campaign manager does not need to be trusted with an off-chain promise.
Why the factory matters more than the homepage
The trust model starts with CampaignFactory. Instead of letting anyone deploy a lookalike contract, the app uses one known factory to spawn campaigns with the same logic every time.
That matters more than it sounds. In a system where users are sending money to a contract, the code itself is the platform's reputation.
The spending gate: one request, one vote threshold
The core contract logic is simple, and that is the point. A manager creates a request. Approvers vote yes. When the majority threshold is crossed, the request can be finalized and funds can move.
function approveRequest(uint index) public {
Request storage request = requests[index];
require(approvers[msg.sender]);
require(!request.complete);
require(!request.approvals[msg.sender]);
request.approvals[msg.sender] = true;
request.approvalCount++;
}
function finalizeRequest(uint index) public restricted {
Request storage request = requests[index];
require(request.approvalCount > (approversCount / 2));
require(!request.complete);
request.complete = true;
request.recipient.transfer(request.value);
}
There is no separate rejection state. No votes are not tracked. That keeps the contract lean, but it also means silence is treated as absence, not opposition.
| Model | Who can spend money | Who approves spending | Trust mechanism | Weakness |
|---|---|---|---|---|
| Kickstarter-style centralized platform | The platform or campaign owner after platform rules are met | The platform's process and terms | Legal and operational trust in the intermediary | Users must trust a central operator |
| This repo's campaign contract | Only the manager after majority approval | Contributors who have funded the campaign | Smart contract rules and on-chain majority threshold | Requests can stall if voters ignore them |
| A broader DAO treasury model | Token holders, multisig signers, or delegates | Governance participants with voting power | Governance contracts plus organizational process | Heavier coordination and more complexity |
The table is the real story. Authority moves away from a platform, and it also moves away from a founder's discretion. The money can only move when the contract says the crowd has agreed.
How the web app stays usable for ordinary users
The frontend is the bridge that keeps this from feeling like a lab demo. The repo uses Next.js, Web3.js, and custom routing so the app can load campaign pages, fetch summaries, and still work when a browser wallet is missing.
if (typeof window !== 'undefined' && typeof window.web3 !== 'undefined') {
web3 = new Web3(window.web3.currentProvider);
} else {
const provider = new Web3.providers.HttpProvider(
'https://rinkeby.infura.io/v3/...'
);
web3 = new Web3(provider);
}
That fallback matters. The app can render read-only data for visitors who do not have MetaMask installed, which makes it much closer to a normal website than a wallet-only tool.
The real lesson is gas discipline
This repo is educational, but it is not casual. It shows the kind of thinking Solidity demands: prefer storage when mutating on-chain data, avoid array scans when a mapping gives you O(1) lookup, and keep state minimal when the chain is the database.
The comment-less design choice that matters most is the yes-only approval model. It reduces storage and logic, but it also reveals a trade-off: simplicity comes from assuming inaction is enough to block finalization unless a majority actively agrees.
| Pattern | Why it helps | What it costs |
|---|---|---|
| <code>Request storage request = requests[index];</code> | Mutates on-chain data without copying the struct | Requires careful understanding of reference semantics |
| <code>mapping(address => bool)</code> for approvers | Fast membership checks with no iteration | You do not get an ordered list of voters |
| Majority threshold only tracks yes votes | Less storage and simpler logic | No explicit negative vote record |
That is the real educational payoff. The repo teaches that smart contracts are not just about logic. They are about choosing which facts deserve to exist on-chain at all.
A prototype, but a useful one
Compared with more feature-rich crowdfunding platforms, this app is tiny. Compared with many DAO systems, it is intentionally narrower. But that narrowness is the point: it isolates the primitives behind decentralized fundraising and makes them easy to inspect.
If you want a clean mental model for how governance can be attached to funding, this repo is enough. It shows that the hard problem is not collecting money. It is turning that money into a controlled right to spend.