My Attempt to build a GoFundMe version on the Ethereum Blockchain part 1

Gbenro Adesoye
Coinmonks
7 min readNov 30, 2018

--

I have been learning to become a blockchain developer for months, and thankful to some free resources on places like Reddit, Medium, GitHub, YouTube and some paid ones on Udemy, I can now confidently say I am no longer a beginner but definitely not an expert yet. There is still more to learn especially as this space is changing rapidly.

The Blockchain has many use cases and this is a good one, some people might argue why do we need a Dapp for this, so for argument sake, this is just for learning purposes. There are many parts that go into building a Dapp but writing the solidity contract is a good place to start. Now let's get into the contract.

Photo by rawpixel on Unsplash

Note: this post is targetted towards beginners so I will be going into details of the smart contract logic

The following will be the public variables in the contract

address public recipient;

This is the address of whoever is raising the fund. They will be the one to call the contract.

string public description;

This is the description of what the money will be used for, so we can keep that info along with the fundraiser in the blockchain.

string public firstName;

The name of the person trying to raise money.

string public lastName;

The name of the person raising money.

Note: I know people can just create funds with any name, but ID verification is not the focus of this contract

uint public amountNeeded;

This is the amount of money that is needed to be raised, in Wei.

mapping(address => uint) public donorsAmount;

This will map the amount of money donated by each donor to the donor’s address

uint public donors;

This is to keep track of the numbers of donors in the contract. A good helper method for the front end application

uint public amountSoFar;

This will keep track of the amount of money donated so far in the fundraiser. This contract allows for the recipient i.e contract creator to be able to withdraw funds anytime, therefore we need a way to keep track of the monies already donated to this contract to know when we reach the goal.

Donation [] public donations;

We use this to keep track of all the donations to this contract. This is a struct object, a good helper method for the front end app but it is not really needed as we already have the donorsAmount mapping.

Bool public ongoing = true;

This is to help us know if the fundraiser is still ongoing. Set to true at the start.

We will need some events that will broadcast to the blockchain when some important things happen in our contract.

event Contract_Created(address indexed _from, address indexed _contract, string);

Event for when a contract is created. Shows owner address, contract address and description of the fundraiser

event Funds_Donated(address indexed _from, address indexed _contract, uint _value);

Event for when money is donated. Shows address of donor, fundraiser contract address and value donated

event Goal_Reached(address indexed _from, address indexed _contract, uint _value);

Event for when the fundraising goal is reached. Shows recipient address, contract address and amount raised

event Fundraiser_Ended(address indexed _from, address indexed _contract, uint _value );

event for when recipient/contract owner ends fundraiser. Shows the owner address, contract address and amount raised

event Fund_Withdrawn(address indexed _from, address indexed _contract, uint _value);

event for when the recipient withdraws money from the fundraiser contract. shows the owner address, contract address and amount withdrawn

We will also need some modifiers that will help us with some restrictions in our contract.

The restricted modifier will allow only the recipient aka contract creator to only call certain functions in the contract.

The isLive modifier will help us end the fundraiser when the goal is reached or when the recipient decides that he wants to end the fundraiser regardless of the goal been reached.

I wanted to destroy the contract when the goal is reached but doing so will delete access to all the info of the contract. This way even if the fundraiser is ended, we will still be able to have access to the info about this contract.

Here we are initializing the contract. Using the firstName, lastName, description, amount need and the recipient. Then we emit an event Contract_created.

Now we can start working on the functions

The donate function is set to be a public function, so anyone can donate, the isLive modifier is there to check if this fundraiser is still ongoing and we have payable, this allows the contract to accept funds when called.

So in this function, we map the sender’s address to the amount of money donated. We increment the amountSoFar with the amount donated. Increased the number of donors by one. We created a new donation, we have not created this function yet. We also emitted the event Funds_Donated.

We also added the logic that will end the contract when we have reached our goal, basically, if we have gotten the amount needed, we should call the private function _end(), which we are going to create later.

Our next function is _createDonation

This is a private function that takes a donor’s address and amount donated, creates a new donation and adds it to the donations array we declared earlier. It is called whenever someone donates to the fundraiser.

The next function is withdraw().

This function is set to public, it is restricted so only the recipient can call it and also checking whether the fundraiser is still ongoing- no point trying to withdraw funds when the fundraiser has ended. So in here, we get the balance of the contract by calling a helper function getBalance (we will create later) and save it into a uint called balance. We check if balance is not 0, then we emit the event Fund_Withdrawn. Finally, we transfer the balance of the contract to the recipient.

So let’s create the getBalance function, very simple

It is public, set to view since it is not modifying any data, just reading, we are also checking whether the fundraiser is live, I guess this is not necessary so you don’t have to use it here. We just return a uint containing the balance.

The next function is end()

This is a public function that is restricted i.e only the recipient can call it, and can only be called when it is ongoing. This function should be called when the recipient decides to end the fundraiser for whatever reason. First, we set ongoing to false. Followed by emitting the event Fundraiser_Ended. Then we send the balance of the contract to the recipient.

We also have another end function, but this one is private and called by the contract. Remember earlier in the donate function when we call _end().

Here its the same logic as the other end function only that it is private and emits the event Goal_Reached.

The link to the full smart contract is here

So, folks, this is the end of our FundMe contract, or is it?

Well, we can definitely do some things to add more safety to our contract and do some optimization to save gas. But this works fine as it is now.

My next post will be about compiling and deploying so we can run some test with mocha.

Then in a future post, I will be doing a smart contract audit, where we can look at areas that can be improved.

Here is the link for the part two

Click to read today’s top story

--

--