Building a Crypto Charity DApp for Crowdfunding Using Next.JS, Solidity, IPFS and Truffle | by Abhishek Chauhan | November, 2022

Set up a fundraising campaign, donate to MATIC, create a receipt, and withdraw

Image by rawpixel.com on Freepik

Let’s build a full-stack Web3 application for fundraising. We will be using NeXT.js, Material-UI, CryptoCompare (ETH – USD conversion), Truffle, Web3Modal and OpenZeppelin contracts to build our web3 application.

Work:

  • Create a fundraising campaign
  • Users can donate to MATIC
  • ETH β€” Converting USD to Avoid Donation Mistakes
  • A beneficiary can withdraw the donated amount
  • Donors can view last donation and create receipt

The first thing we need to do is clone the template:

git clone https://github.com/ac12644/Crypto-Charity.git
cd fundraiser
yarn

Next, you will need to create new files for our contracts. First, let’s create all the empty files for our contracts:

touch contracts/FundraiserFactory.sol
touch contracts/Fundraiser.sol

we also have to install OpenZeppelin Because we are using proprietary contract:

yarn add @openzeppelin/contracts

Now, I Fundraiser.sol file, import Ownable And SafeMath From OpenZeppelin:

move on with us Fundraiser.sol Smart contract, let’s define a structure for donation:

Structures in Solidity allow us to create new data types. These data types will have properties that can be of different types. For example, we can use the following code to generate a generate Donation structure:

struct Donation {
uint256 value;
uint256 date;
}

Mapping allows you to associate keys with values. To declare a mapping, you need to specify the types of the key and value as shown below:

mapping(address => Donation[]) public _donations;

This mapping associates an address with a dynamic array of donations. If we wish to use a donation from an individual donor, we use [ ] Notation:

address donor = msg.sender;
_donations[donor];

Now we will add the constructor and state variable to the contract. We are keeping the address of the payable beneficiary to transfer the amount raised. The addresses will represent both the beneficiary and the custodian. The custodian’s address is the address associated with the fundraiser’s manager. This address will not receive any funds, but will be the address that allows the beneficiary to make changes and request the transfer of funds.

setBeneficiary The function will fail if it is called by someone other than the owner. If the sender is the owner, it will update the beneficiary’s address with the address passed as a parameter:

function setBeneficiary(address payable _beneficiary) 
public onlyOwner { beneficiary = _beneficiary; }

Now we a. will build donate Function that accepts ether. To do this we need to add the payable modifier to our function declaration. When we send Ether to a contract or EOA, their balance will automatically increase – we don’t need to add any code to generate this behavior.

to create myDonationsCountFunction that should return the donation count for the requesting donor.

function myDonationsCount() public view returns (uint256) { 
return _donations[msg.sender].length;
}

myDonations The function must be created to return the donation made by the donor to the fundraiser. Unfortunately, it is impossible to return an array of a struct from external or public functions due to limitations in the current ABI. As a result, we have to use multiple return values ​​and arrays.

Next, define the withdrawal function and use it onlyOwnerModifiers to restrict access and emit withdraw Competition.

event Withdraw(uint256 amount);function withdraw() public onlyOwner {
uint256 balance = address(this).balance;
beneficiary.transfer(balance);
emit Withdraw(balance);
}

To avoid test failure, we should include a payable fallback function. Now let’s add one:

fallback() external payable {
totalDonations = totalDonations.add(msg.value);
donationsCount++;
}

Now our fundraising contract is ready. After completion, it will look like this:

the previous one Fundraiser The contract was loaded with features, but it could not be used to build anything. In this contract, we’ll add the missing pieces using a common design pattern: the factory pattern.

move on with us FundraiserFactory Contract, let’s set up a new state variable to store the fundraiser we created on our contract. Then we’ll need to create a function to get the length of the collection.

Now we take all the parameters from the form and then start a new fundraiser using createFundraiserCeremony and emission of an event that will include the fundraiser and owner address:

We need a way to display the fundraisers available to our users. One option would be to retrieve all the fundraisers created in a single call to our contract, as we did for myDonations function in our Fundraiser Contract. This approach is fine when we expect the size of the collection to remain relatively small, but if our app becomes popular, we would like to load this data in smaller chunks.

Even though it costs nothing (in gas) to view the data from the blockchain, it still uses up the resources on the EVM. If a user comes to our application and immediately sees the fundraiser they want, we waste a lot of those resources. Smaller chunks will also allow our page to render faster than if we wait for all the items from a single request to return.

The size of the returned collection is going to be smaller than fundraisersCountor the range being requested:

now our FundraiserFactory The contract is ready. After completion, it will look like this:

Deploy the contract on Polygon Mumbai by running, add the env field before deployment:

truffle deploy --network mumbai

javascript function

In this part, we’ll walk through calling these functions on the front-end so that you understand how to interact with deployed smart contracts.

We start by adding the necessary functions to create a new fundraiser. move to src/views/Create/components/Form/Form.js,

The first step is to initialize Web3 authentication via MetaMask. For this, we are using web3modal, and then we connect our deployed smart contract FundraiserFactory,

As we are uploading an image, we need to create an IPFS client for uploading the file, and for that we are using Infura Gateway. You will need to obtain Project ID, Secret Key and Dedicated Subdomain Gateway from Infura.

The final step in the form is to create a submit function that will create a fundraiser on the Polygon Network.

Here’s what it looks like when you put it all together:

Form

Now that we can generate a new fundraiser, we should add a frontend so that the fundraiser appears on the page along with any other fundraisers we have created. Once we have the UI for displaying the fundraiser, we can use a modal so that the user can click on a specific fundraiser and donate. However, we should start by displaying a list of fundraisers.

are going src/views/Projects/Projects.js,

Now that we’ve got the data from our contract, we’ll work on the frontend to display each Fundraiser card to the user. The first thing we need to do is create a new component for our display Card Component:

are going src/blocks/FundraiserCard/FundraiserCard.js,

Now, switch Projects.js file, we will iterate through the list of fundraisers and display Card Components for each:

Adding detailed information about each fundraiser

Copy the following code, and add it to Projects.js,

fundraiser model

For the GitHub repo, visit https://github.com/ac12644/Crypto-Charity.git.

Thanks for reading!

Leave a Comment