project screenshot 1
project screenshot 2
project screenshot 3

Donation_platform

This Web3 crowdfunding application is a decentralized platform built on the Ethereum blockchain that allows users to create and contribute to fundraising projects.

Donation_platform

Created At

ETHGlobal Bangkok

Project Description

Certainly! I'll modify the smart contract to include a matching donor and create a more comprehensive frontend for the application. Here's the updated implementation:

First, let's update the Solidity smart contracts:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CrowdfundingProject {
    address public creator;
    address public matchingDonor;
    string public description;
    uint256 public goal;
    uint256 public totalFunds;
    uint256 public matchedFunds;
    bool public isClosed;

    event FundReceived(address donor, uint256 amount);
    event MatchedFundReceived(uint256 amount);
    event ProjectClosed(uint256 totalRaised);

    constructor(address _creator, string memory _description, uint256 _goal) {
        creator = _creator;
        description = _description;
        goal = _goal;
        totalFunds = 0;
        matchedFunds = 0;
        isClosed = false;
    }

    function setMatchingDonor(address _matchingDonor) public {
        require(msg.sender == creator, "Only creator can set matching donor");
        require(matchingDonor == address(0), "Matching donor already set");
        matchingDonor = _matchingDonor;
    }

    function donate() public payable {
        require(!isClosed, "Project is closed");
        totalFunds += msg.value;
        emit FundReceived(msg.sender, msg.value);

        if (matchingDonor != address(0)) {
            matchedFunds += msg.value;
            emit MatchedFundReceived(msg.value);
        }

        if (totalFunds + matchedFunds >= goal) {
            isClosed = true;
            emit ProjectClosed(totalFunds + matchedFunds);
        }
    }

    function matchFunds() public payable {
        require(msg.sender == matchingDonor, "Only matching donor can match funds");
        require(!isClosed, "Project is closed");
        require(msg.value == matchedFunds, "Must match exact amount");

        totalFunds += msg.value;
        matchedFunds = 0;

        if (totalFunds >= goal) {
            isClosed = true;
            emit ProjectClosed(totalFunds);
        }
    }

    function withdraw() public {
        require(msg.sender == creator, "Only creator can withdraw");
        require(isClosed, "Project is not closed yet");
        payable(creator).transfer(address(this).balance);
    }
}

contract CrowdfundingFactory {
    CrowdfundingProject[] public projects;

    event ProjectCreated(address projectAddress, address creator, string description, uint256 goal);

    function createProject(string memory _description, uint256 _goal) public {
        CrowdfundingProject newProject = new CrowdfundingProject(msg.sender, _description, _goal);
        projects.push(newProject);
        emit ProjectCreated(address(newProject), msg.sender, _description, _goal);
    }

    function getProjects() public view returns (CrowdfundingProject[] memory) {
        return projects;
    }
}

Now, let's create a more comprehensive frontend using HTML, CSS, and JavaScript with Web3.js:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web3 Crowdfunding</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/web3.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        h1, h2 {
            color: #333;
        }
        input, button {
            margin: 5px 0;
            padding: 5px;
        }
        .project {
            border: 1px solid #ddd;
            padding: 10px;
            margin: 10px 0;
            border-radius: 5px;
        }
        .progress-bar {
            background-color: #e0e0e0;
            height: 20px;
            border-radius: 10px;
            margin: 10px 0;
        }
        .progress {
            background-color: #4CAF50;
            height: 100%;
            border-radius: 10px;
            text-align: center;
            line-height: 20px;
            color: white;
        }
    </style>
</head>
<body>
    <h1>Web3 Crowdfunding</h1>
    
    <h2>Create Project</h2>
    <input id="description" type="text" placeholder="Project Description">
    <input id="goal" type="number" placeholder="Funding Goal (in ETH)">
    <button onclick="createProject()">Create Project</button>

    <h2>Projects</h2>
    <div id="projects"></div>

    <script>
        let web3;
        let factoryContract;
        const factoryAddress = "YOUR_FACTORY_CONTRACT_ADDRESS";
        const factoryABI = []; // Add your factory contract ABI here
        const projectABI = []; // Add your project contract ABI here

        async function init() {
            if (typeof window.ethereum !== 'undefined') {
                web3 = new Web3(window.ethereum);
                try {
                    await window.ethereum.enable();
                    factoryContract = new web3.eth.Contract(factoryABI, factoryAddress);
                    loadProjects();
                } catch (error) {
                    console.error("User denied account access");
                }
            } else {
                console.log('Please install MetaMask!');
            }
        }

        async function createProject() {
            const description = document.getElementById('description').value;
            const goal = web3.utils.toWei(document.getElementById('goal').value, 'ether');
            const accounts = await web3.eth.getAccounts();

            await factoryContract.methods.createProject(description, goal).send({ from: accounts[0] });
            loadProjects();
        }

        async function loadProjects() {
            const projectsDiv = document.getElementById('projects');
            projectsDiv.innerHTML = '';

            const projects = await factoryContract.methods.getProjects().call();

            for (let i = 0; i < projects.length; i++) {
                const projectContract = new web3.eth.Contract(projectABI, projects[i]);
                const description = await projectContract.methods.description().call();
                const goal = await projectContract.methods.goal().call();
                const totalFunds = await projectContract.methods.totalFunds().call();
                const matchedFunds = await projectContract.methods.matchedFunds().call();
                const isClosed = await projectContract.methods.isClosed().call();
                const matchingDonor = await projectContract.methods.matchingDonor().call();

                const progress = ((parseInt(totalFunds) + parseInt(matchedFunds)) / parseInt(goal)) * 100;

                const projectElement = document.createElement('div');
                projectElement.className = 'project';
                projectElement.innerHTML = `
                    <h3>${description}</h3>
                    <p>Goal: ${web3.utils.fromWei(goal, 'ether')} ETH</p>
                    <p>Raised: ${web3.utils.fromWei(totalFunds, 'ether')} ETH</p>
                    <p>Matched Funds: ${web3.utils.fromWei(matchedFunds, 'ether')} ETH</p>
                    <p>Status: ${isClosed ? 'Closed' : 'Open'}</p>
                    <div class="progress-bar">
                        <div class="progress" style="width: ${progress}%">${progress.toFixed(2)}%</div>
                    </div>
                    ${!isClosed ? `
                        <input id="amount-${i}" type="number" step="0.01" placeholder="Amount in ETH">
                        <button onclick="donate(${i})">Donate</button>
                        ${matchingDonor === '0x0000000000000000000000000000000000000000' ? `
                            <input id="matching-donor-${i}" type="text" placeholder="Matching Donor Address">
                            <button onclick="setMatchingDonor(${i})">Set Matching Donor</button>
                        ` : `
                            <button onclick="matchFunds(${i})">Match Funds</button>
                        `}
                    ` : ''}
                `;
                projectsDiv.appendChild(projectElement);
            }
        }

        async function donate(index) {
            const projects = await factoryContract.methods.getProjects().call();
            const projectContract = new web3.eth.Contract(projectABI, projects[index]);
            const amount = document.getElementById(`amount-${index}`).value;
            const accounts = await web3.eth.getAccounts();

            await projectContract.methods.donate().send({ 
                from: accounts[0], 
                value: web3.utils.toWei(amount, 'ether') 
            });
            loadProjects();
        }

        async function setMatchingDonor(index) {
            const projects = await factoryContract.methods.getProjects().call();
            const projectContract = new web3.eth.Contract(projectABI, projects[index]);
            const matchingDonorAddress = document.getElementById(`matching-donor-${index}`).value;
            const accounts = await web3.eth.getAccounts();

            await projectContract.methods.setMatchingDonor(matchingDonorAddress).send({ from: accounts[0] });
            loadProjects();
        }

        async function matchFunds(index) {
            const projects = await factoryContract.methods.getProjects().call();
            const projectContract = new web3.eth.Contract(projectABI, projects[index]);
            const accounts = await web3.eth.getAccounts();
            const matchedFunds = await projectContract.methods.matchedFunds().call();

            await projectContract.methods.matchFunds().send({ 
                from: accounts[0], 
                value: matchedFunds 
            });
            loadProjects();
        }

        init();
    </script>
</body>
</html>

This updated implementation includes the following new features:

  1. A matching donor can be set for each project.
  2. The matching donor can match the funds raised by other donors.
  3. The frontend now displays more information about each project, including matched funds and a progress bar.
  4. The UI has been improved with some basic CSS styling.

To use this code:

  1. Deploy the updated CrowdfundingFactory contract to your preferred Ethereum network.
  2. Replace YOUR_FACTORY_CONTRACT_ADDRESS with the deployed factory contract address.
  3. Add the correct ABIs for both the factory and project contracts.
  4. Serve the HTML file using a local web server or host it on a web server.

This implementation allows users to:

  • Create new projects by providing a description and funding goal
  • View all created projects with detailed information
  • Donate to open projects
  • Set a matching donor for a project
  • Match funds as the matching donor
  • Automatically close projects when they reach their funding goal

Remember that this is still a basic implementation and would need additional features, error handling, and security measures for a production-ready application. You should also consider implementing proper testing, gas optimization, and using more advanced patterns like upgradeable contracts for a real-world application.

How it's Made

Here's a description of the Web3 crowdfunding application:

Decentralized Crowdfunding Platform with Matching Donations

This innovative Web3 application revolutionizes the crowdfunding landscape by leveraging blockchain technology to create a transparent, efficient, and engaging fundraising experience. Built on the Ethereum network, this decentralized platform allows anyone to launch and contribute to fundraising projects with ease and security.

Key Features:

  1. Project Creation: Users can effortlessly create fundraising projects by providing a description and setting a funding goal in ETH. Each project is represented by a unique smart contract on the Ethereum blockchain, ensuring transparency and immutability of project details.

  2. Donation Mechanism: Contributors can support projects by making direct ETH donations. The smart contract automatically tracks and updates the total funds raised, providing real-time progress information.

  3. Matching Donor System: A unique feature of this platform is the ability to designate a matching donor for each project. This matching donor can double the impact of contributions by matching the funds raised, potentially accelerating the project's progress towards its goal.

  4. Automatic Closure: To maintain efficiency and prevent overfunding, projects automatically close once they reach their funding goal. This feature ensures that funds are allocated as intended and prevents unnecessary accumulation of excess donations.

  5. Real-time Progress Tracking: The user-friendly interface displays a visual progress bar for each project, allowing users to quickly assess how close a project is to reaching its goal. Detailed information about total funds raised, matched funds, and project status is readily available.

  6. Blockchain Security: By utilizing Ethereum smart contracts, the platform ensures that all transactions and project details are secure, transparent, and immutable. This blockchain-based approach eliminates the need for intermediaries and reduces the risk of fraud.

  7. Decentralized Architecture: The application operates on a decentralized network, reducing single points of failure and ensuring continuous availability of the platform.

  8. User-Friendly Interface: Despite its advanced blockchain underpinnings, the application features an intuitive and responsive web interface, making it accessible to users regardless of their technical expertise.

This Web3 crowdfunding platform combines the power of blockchain technology with the spirit of collaborative fundraising, creating a robust ecosystem for project creators and supporters alike. Whether you're an entrepreneur seeking funding for your next big idea, a philanthropist looking to make a difference, or an enthusiast eager to support innovative projects, this platform provides a secure, transparent, and engaging way to participate in the future of crowdfunding.

background image mobile

Join the mailing list

Get the latest news and updates