Project Objectives – by building this project you will:
  • 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
PartDetails
BlockAccount.solStructs Fundraiser { name, fundraiserAddress, userIdCard }, Donor { name, donorAddress, userIdCard }, FundTicket { title, details, activeStatus, fundAmount, currentCollection, fundraiserAddress }
CrowdfundingContract.solContract CrowdFunding; imports contracts/BlockAccount.sol. (Save the struct file under this exact name – the resource link is labelled accordingly.)
stateaddress payable fundManager, FundTicket public ticket, registration counters
mappingsfundraiserList and donorList (index → user)
modifiersRegistration checks (not already registered / must be registered), ticket status checks, checkDonateAmount(uint) and checkReleaseFundAmount() (convert ETH to wei and compare with msg.value), checkFundManager
functionsfundraiserRegister, DonorRegister, RaiseFundTicket(title, details, fundAmount), DonateNow(ethAmount) (payable), releaseFundAmount() (payable, manager only)
How It Works
1. RegisterFundraisers and donors register
2. TicketA fundraiser opens a campaign with a target
3. DonateDonors send Ether; it is forwarded to the Fund Manager
4. CloseTicket closes when the target is reached
5. ReleaseManager sends the collected amount to the fundraiser

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 and transfer (Chapters 14, 24).
  • Constructor setting the admin (Chapter 17).
How to Run in Remix
  1. Create contracts/BlockAccount.sol (struct file) and contracts/CrowdfundingContract.sol; compile and deploy CrowdFunding from the first account (Fund Manager).
  2. Account 2: fundraiserRegister, then RaiseFundTicket("School books", "…", 10).
  3. Accounts 3 and 4: DonorRegister, then set VALUE to e.g. 4 ether and call DonateNow(4) (the argument must match the Ether sent).
  4. Read ticket to see currentCollection.
  5. 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 versionImprovement 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)

Answer : Crowdfunding depends on trust between donors, intermediaries and fundraisers. Recording registrations, campaigns and donations on a blockchain makes the process transparent and auditable.

Answer : Fundraiser (name, fundraiserAddress, userIdCard), Donor (name, donorAddress, userIdCard) and FundTicket (title, details, activeStatus, fundAmount, currentCollection, fundraiserAddress).

Answer : A fundraising campaign stored in the FundTicket struct, with a title, details, a target amount (fundAmount), the amount collected so far (currentCollection) and an active status.

Answer : The account that deploys the contract; the constructor stores it with fundManager = payable(msg.sender);.

Answer : It converts the ethAmount argument to wei by multiplying by 10^18 and requires msg.value to be exactly that amount.

Answer : DonateNow forwards it immediately to the Fund Manager with transfer; the manager later releases the collected amount to the fundraiser.

Answer : When currentCollection reaches or exceeds fundAmount after a donation, or when the Fund Manager releases the funds.

Answer : Both receive Ether with the call – the donor’s donation and the manager’s released amount – which is only possible in payable functions.

Answer : Only one, because the contract stores a single ticket variable and checkFundTicketStatus prevents creating a new ticket while one is active.

Answer : All blockchain data is public and permanent, so identity numbers would be exposed to everyone and could never be deleted. Personal data should be kept off-chain.

Answer : Donations are sent to the manager’s account, so the fundraiser depends on the manager to release them. Keeping funds in the contract with automatic release would remove that dependency.

Answer : Add a deadline and, if the target is not reached by then, allow each donor to withdraw their recorded donation through a refund function.

Answer : Because CrowdfundingContract.sol imports "contracts/BlockAccount.sol"; the file must exist at that path for the import to compile.

Answer : It requires msg.value sent by the manager to equal the ticket’s currentCollection converted to wei.

Answer : Store campaigns in a mapping such as 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.

Q1. In the Crowdfunding contract, donated Ether is first sent to:

Show Answer

Correct Answer : B. The Fund Manager
DonateNow calls fundManager.transfer(msg.value).

Q2. A donor calls DonateNow(4). msg.value must be:

Show Answer

Correct Answer : C. 4 × 10^18 wei
checkDonateAmount converts ETH to wei.

Q3. Which data should NOT be stored on a public blockchain?

Show Answer

Correct Answer : D. Personal ID card numbers
Personal data on-chain is public and permanent.

Q4. Which modifier prevents a second active campaign?

Show Answer

Correct Answer : B. checkFundTicketStatus
It requires ticket.activeStatus to be false.

Q5. A trust-minimised improvement would keep donations:

Show Answer

Correct Answer : D. In the contract (escrow) until release conditions are met
Escrow removes reliance on the manager.

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.

  1. 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
  2. Solidity Team. (n.d.). Units and Globally Available Variables. Solidity Documentation. https://docs.soliditylang.org/en/latest/units-and-global-variables.html
  3. Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
  4. ethereum.org. (n.d.). Smart contract security. Ethereum Developer Documentation. https://ethereum.org/en/developers/docs/smart-contracts/security/
  5. Remix Project. (n.d.). Remix IDE Documentation. https://remix-ide.readthedocs.io/en/latest/
  6. 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.