- Register two kinds of users (fundraisers and donors) with structs and mappings.
- Run a fundraising campaign (“fund ticket”) with a target and collection status.
- Accept Ether donations and release funds with payable functions and
transfer.
Synopsis
Fundraising depends on trust: donors want to know that their money reaches the right cause, and organisations need donors’ confidence to collect funds – a need that became very visible during emergencies such as the Covid-19 pandemic. Recording registrations, campaigns and donations on a blockchain makes every step transparent and auditable.
In this project the deploying account is the Fund Manager. Fundraisers register and open a fund ticket (a campaign with a title, details and a target amount in ETH). Registered donors donate Ether to the active ticket; the contract tracks the collected amount and closes the ticket when the target is reached. The Fund Manager then releases the collected amount to the fundraiser.
Contract Architecture
| Part | Details |
|---|---|
| BlockAccount.sol | Structs Fundraiser { name, fundraiserAddress, userIdCard }, Donor { name, donorAddress, userIdCard }, FundTicket { title, details, activeStatus, fundAmount, currentCollection, fundraiserAddress } |
| CrowdfundingContract.sol | Contract CrowdFunding; imports contracts/BlockAccount.sol. (Save the struct file under this exact name – the resource link is labelled accordingly.) |
| state | address payable fundManager, FundTicket public ticket, registration counters |
| mappings | fundraiserList and donorList (index → user) |
| modifiers | Registration checks (not already registered / must be registered), ticket status checks, checkDonateAmount(uint) and checkReleaseFundAmount() (convert ETH to wei and compare with msg.value), checkFundManager |
| functions | fundraiserRegister, DonorRegister, RaiseFundTicket(title, details, fundAmount), DonateNow(ethAmount) (payable), releaseFundAmount() (payable, manager only) |
How It Works
Only one fund ticket can be active at a time. Amounts are entered in whole ETH and converted to wei by the modifiers.
Key Requirements (Concepts Used)
- Structs and mappings for users and campaigns (Chapters 12, 13).
- Modifiers with and without arguments (Chapter 22).
- Payable functions,
msg.value, ETH-to-wei conversion andtransfer(Chapters 14, 24). - Constructor setting the admin (Chapter 17).
How to Run in Remix
- Create
contracts/BlockAccount.sol(struct file) andcontracts/CrowdfundingContract.sol; compile and deploy CrowdFunding from the first account (Fund Manager). - Account 2:
fundraiserRegister, thenRaiseFundTicket("School books", "…", 10). - Accounts 3 and 4:
DonorRegister, then set VALUE to e.g. 4 ether and callDonateNow(4)(the argument must match the Ether sent). - Read
ticketto seecurrentCollection. - Fund Manager: set VALUE equal to the collected ETH and call
releaseFundAmount(); the fundraiser’s balance increases.
Limitations and Extension Exercises
| Observation in the teaching version | Improvement to try |
|---|---|
| Donations go to the Fund Manager’s account, who must later pay the fundraiser manually – donors still have to trust the manager. | Keep donations in the contract (escrow) and release them automatically when the target is met. |
| If the target is never reached, donors cannot get their money back. | Add a deadline and a refund() function for donors. |
| ID card numbers are stored on a public blockchain. | Never store personal identity data on-chain; keep it off-chain and store only a hash or a verification flag. |
| Only one campaign can exist at a time. | Store campaigns in mapping(uint => FundTicket) with a campaign ID. |
| Registration checks loop over all users. | Use mapping(address => bool) lookups. |
Key Takeaways
- Structs and mappings model fundraisers, donors and campaigns.
- Payable functions with amount checks handle Ether donations and fund release.
- True trust-minimised crowdfunding keeps funds in escrow, supports refunds and keeps personal data off-chain.
Video : Project 4 : Smart Contract for Crowdfunding System
Resource Files
Question / Answer (15 questions)
fundManager = payable(msg.sender);.mapping(uint => FundTicket) campaigns with a campaign counter, and pass the campaign ID to donate and release functions.MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.
- Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
- Solidity Team. (n.d.). Units and Globally Available Variables. Solidity Documentation. https://docs.soliditylang.org/en/latest/units-and-global-variables.html
- Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
- ethereum.org. (n.d.). Smart contract security. Ethereum Developer Documentation. https://ethereum.org/en/developers/docs/smart-contracts/security/
- Remix Project. (n.d.). Remix IDE Documentation. https://remix-ide.readthedocs.io/en/latest/
- Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.