Making the simplest Ethereum Dapp based off Patreon — Part 1. Making the smart contract

Bryan Edison
Coinmonks
Published in
8 min readMay 9, 2018

--

Ethereum Logo

If you’ve been keeping up with tech news lately, you might have noticed the craze around blockchain technology and cryptocurrencies. On an almost equal proportion are the skeptics who cry “it’s a bubble!”, and while there is truth to that claim, much of that claims falls on the numerous alt-coins that are created by the hundreds every week, as well as the erratic price surges of popular coins such as Bitcoin.

Bitcoin is indeed the most well-known cryptocurrency today, but for the smart contract we will be building today we will instead focus on implementing it on the Ethereum Blockchain. The reason why is that Bitcoin’s smart contract language is not as developed as Ethereum’s smart contract language, Solidity. This is partly due to Bitcoin’s programming language being purposely designed to not be Turing complete in order to prevent any malicious attacks.

In this article, we will making a simple smart contract in Ethereum’s smart contract language, Solidity.We will basing this off of a crowdfunding site called Patreon. Users will be able to create new campaigns and visitors will be able to contribute Ether to user causes.

If interested or want to brush up on Solidity before continuing further, here are the Solidity docs for the version of Solidity we will be using, 0.4.17.

Another important tool to become familiar with is Remix, which is an online compiler for Solidity. With this tool, you can create, compile, debug and deploy your smart contracts to the Ethereum Blockchain as well as to your local machine. Upon visiting the page, you will notice that the text editor already has smart contract constructed. Feel free to browse and make sense of it!

Whenever you are ready to continue on, delete the code on the editor as we’ll start a fresh, new, custom-built contract.

After deletion, write this into your editor:

pragma solidity ^0.4.17;

The line of code above simply states the version of solidity we will be using in this contract. In this instance, we will be using version 0.4.17.

Following this line we will then write:

pragma solidity ^0.4.17;contract PatreonFactory {}

This line of code will make our first contract, which is similar to a class in object-oriented languages. This contract will contain persistent data such as variables, as well as functions that can modify these variables. This contract will be the contract that will be called to create other contract instances, which in this case will make individual Patreon pages. All this contract will do is create individual Patreon pages and also retrieve all Patreon pages it has created.

We will then write a function called createPatreon, which will be placed within our contract:

pragma solidity ^0.4.17;contract PatreonFactory {

function createPatreon() public {
new Patreon(msg.sender);
}
}

Keep in mind that Solidity is a statically-typed language, which means that the type of each variable needs to be specified. For example, in our createPatreon function, we take in two parameters but we also specify the data type of each parameter, which in this case are both strings. Following our parameters is the word “public”, which states that this function can be called both internally from within the contract but also externally.

More on this here: http://solidity.readthedocs.io/en/v0.4.21/contracts.html#visibility-and-getters

Lastly, inside this function we will call new Patreon, which takes in the parameter msg.sender. Msg.sender is a variable that is the address of the wallet id pertaining to the person who created the specific contract. The following parameters are type string, and are our title and description, which are now recognized by those variable names. If you notice however, msg.sender isn’t included in our original parameters for our createPatreon function. This is because msg.sender is implicitly included in our function calls. There are a few other implicitly included variables out there as well in Solidity.

Our new createPatreon will create an instance of the contract called Patreon but oh wait…

That’s right, there’s no contract called Patreon yet!

Let’s make one:

pragma solidity ^0.4.17;contract PatreonFactory {

function createPatreon(string title, string description) public {
new Patreon(title, description, msg.sender);
}
}
contract Patreon {}

Now, we are technically creating an instance of this contract called Patreon.

Let’s fill this new contract with a function, and lets add a little something to your PatreonFactory contract:

pragma solidity ^0.4.17;contract PatreonFactory {
address[] public deployedPatreons;
function createPatreon(string title, string description) public {
address newPatreon = new Patreon(string title, string.description, msg.sender);
deployedPatreons.push(newPatreon);
}
}
contract Patreon { function Patreon(string title, string description, address creator) public {
manager = creator;
patreonTitle = title;
patreonDescription = description;
}
}

Quite a few things are going on here. First, we initialized a public variable in our original contract which is called deployedPatreons, and is type address and stored in an array.

We then seemingly named our instantiation of a new contract as newPatreon and as an address data type. What actually happened is that our instantiation of a new contract returns the address of where it is deployed. We then capture this address as a variable and then push it into our public array called deployedPatreons.

In our new contract, we have a Patreon constructor function which is named the same as our contract. In the parameters field, we see that it has the three parameters field that we passed in. In our third parameter, we are renaming our msg.sender address as creator. We then assign our creator address as manager, and rename our variables accordingly.

Next we will initialize some variables as so:

(This is necessary and should’ve been done before saving our variables from our constructor function parameters)

pragma solidity ^0.4.17;contract PatreonFactory {
address[] public deployedPatreons;
function createPatreon(string title, string description) public {
address newPatreon = new Patreon(string title, string.description, msg.sender);
deployedPatreons.push(newPatreon);
}
}
contract Patreon {address public manager;
uint public contributors;
string patreonTitle;
string patreonDescription;
function Patreon(string title, string description, address creator) public {
manager = creator;
patreonTitle = title;
patreonDescription = description;
}
}

You will notice 4 variables initialized. In this following segment, we will incorporate a function that will use this variable.

pragma solidity ^0.4.17;contract PatreonFactory {
address[] public deployedPatreons;
function createPatreon(string title, string description) public {
address newPatreon = new Patreon(string title, string.description, msg.sender);
deployedPatreons.push(newPatreon);
}
}
contract Patreon {address public manager;
uint public contributors;
string patreonTitle;
string patreonDescription;
function Patreon(string title, string description, address creator) public {
manager = creator;
patreonTitle = title;
patreonDescription = description;
}
function pay() public payable {
require(msg.value > .01 ether);
contributors += 1;
}
}

We created a public function named pay and has ‘payable’ attached after public. This declaration states that this function takes a value of ether. Users can input however much they would like to pay into the function. In this case, we made a require statement within our function that only allows users to input a value of ether greater than 0.1. Afterwards, our contributors variable, which initiates at 0, will be incremented by 1. This will show the number of contributors to date for that specific Patreon campaign.

One reason for this minimum value is that every transaction with contracts in Ethereum costs ‘gas’. ‘Gas’ is a form of measurement of ether, and although transactions are not expensive, it would be nonsensical to donate less than the cost of the transaction. The exception to paying ‘gas’ is when retrieving information from the blockchain.

Lastly, let’s create these three functions within our Patreon contract:


function cashOut() public {
require(msg.sender == manager);
manager.transfer(this.balance);
}

function destroy() public {
require(msg.sender == manager);
selfdestruct(manager);
}

function getInfo() public view returns (
string, string, uint, address
) {
return (
patreonTitle,
patreonDescription,
contributors,
manager

);
}

These three functions will do the following:

  1. Cash out the money donated to us.

2. Destroy the contract, which will return the money within the contract to their respective senders.

3. Retrieve information about the contract.

Functions 1 and 2 will cost us gas, but function 3 won’t. Remember that only functions that manipulate data within the contract costs gas. Functions that only retrieve information do not cost anything to call.

In our function cashOut, we are making a requirement that our manager has to be the invoker of this function. If anyone else were to call this function, the transaction would not execute and an error would show up on Remix. This require statement ensures that only the creator of this contract has access to call this function. In the following line, we are transferring the balance that this contract has accrued. This contract currently holds the sum of money donated by contributors and is locked within the contract until the manager cashes out or destroys the contract.

Our destroy function essentially destroys or self-destructs the function, which gets rid of the specific instance of the contract. This will then return the contributions to their contributors. Generally, it’s good practice to make a destroy function within your contract to ensure that if the requirements are not met, the manager can always elect to destroy the contract in order to not lock in the money within the contract for all eternity.

Our last function will then return information about that particular Patreon campaign including the manager(creator) address, campaign title, campaign description, and the number of contributors.

A little surprise:

We added an additional function inside of our PatreonFactory contract called getDeployedPatreon. . It will serve to get a list of addresses, which are actually the addresses of deployed Patreon campaigns!

One word of caution: Always remember to finish your lines of code with semicolons. Otherwise, during compilation you will get an error.

pragma solidity ^0.4.17;contract PatreonFactory {

address[] public deployedPatreons;


function createPatreon(string title, string description) public {
address newPatreon = new Patreon(title, description, msg.sender);

deployedPatreons.push(newPatreon);
}

function getDeployedPatreon() public view returns (address[]) {
return deployedPatreons;
}

}
contract Patreon {


address public manager;
uint public contributors;
string patreonTitle;
string patreonDescription;


function Patreon(string title, string description, address creator) public {
manager = creator;
patreonTitle = title;
patreonDescription = description;
}

function pay() public payable {
require(msg.value > .01 ether);
contributors += 1;
}

function cashOut() public {
require(msg.sender == manager);
manager.transfer(this.balance);
}

function destroy() public {
require(msg.sender == manager);
selfdestruct(manager);
}

function getInfo() public view returns (
string, string, uint, address
) {
return (
patreonTitle,
patreonDescription,
contributors,
manager

);
}
}

If you liked this post, please feel free to share and give it as many claps as humanely possible. 500 claps for part 2 of this Dapp tutorial and a video walkthrough covering the creation and testing of this smart contract!

Part 2 will be covering creating a front-end and back-end to interact with this smart contract. Stay tuned!

LinkedIn: https://www.linkedin.com/in/bryanedison/

Twitter: @BryanAEdison

Click to learn more about Dapps

--

--

Bryan Edison
Coinmonks

Full Stack Developer. Economics Geek. Environmentalist. Brazilian Jiu Jitsu competitor.