How I built a decentralized Ethereum app for the Super Bowl
Crypto is everywhere now, but I always wondered if people were just going to trade it, or actually use it for something productive.
When I heard that the creator of Ethereum was just a guy working on Bitcoin that wanted to attach code to blockchain transactions, I had to learn more. I also heard the buzz word “decentralized app” (or dApp for short), but I never really could explain what one was.
My attempt to explain how Ethereum is different than Bitcoin.
So, what type of code would be transferred alongside a money transaction? With Ethereum, you write something called a “smart contract”. I had trouble wrapping my head around this until I saw an actual example in code.
Let’s look at a very simple contract:
An inbox contract. Imagine if it cost money to send an email…
Even if you know nothing about Solidity, the language of smart contracts, you can see above that we are initializing a class called
Inbox with a string called
message. It looks like we can
setMessage, and that’s about it.
When you call
setMessage, you’re changing data in the contract, and any time you do that, you have to send a transaction to the Ethereum network.
So decentralized apps are just apps that interact directly with the blockchain.
Sending Money with Contracts
Let’s look at another contract to see how money is moved around:
A lottery contract. Make that money move.
In this one, there is an
enter function that has
payable in the definition. This function expects there to be a value associated with the transaction (in this case 0.1 ETH). Next, there is an
address array that we
msg.sender (the player) into. Finally, the
pickWinner function chooses a random entry in the
players array, and pays them out the balance in the contract with
All of this, by the way, was taught to me by Stephen Grider, who has a class on Udemy called Ethereum & Solidity: The Complete Developer’s Guide.
Deploying a contract to the Ethereum network is pretty easy too:
Once a contract is deployed, you can use the
web3 library to interact with it from a React app.
I had an idea to build an app for the super bowl.
The Big Game Contract
Here’s the idea for the app:
- 12 players
- Each player can choose a team (either “birds”, or “pats”)
- Each player must send 0.015 ETH (about $20) to enter
- If your team wins, you split the pot with everyone else who chose that team
Let’s dive into the contract function by function to understand how this could work.
Let’s get this party started!
BigGame with a
manager (the person who deploys the contract, me), two
address arrays to represent each team, and a
playerIndex mapping of
address => uint. Thin of the
playerIndex mapping as a hash of every single Ethereum address, initialized to zero.
When players enter, I’ll update their
playerIndex so I can display their status on the web page.
+-------------+---------------------+ | playerIndex | status | +-------------+---------------------+ | 0 | Not entered | | 1 | Entered birds | | 2 | Entered pats | | 3 | Entered birds, won | | 4 | Entered pats, won | | 5 | Entered pats, lost | | 6 | Entered birds, lost | | 9 | Refund everybody | +-------------+---------------------+
Yes, if something goes wrong, I have a function that will refund everybody.
One more thing to note:
restricted is a function modifier that we’ll use later on the
pickWinner function. This only lets the
manager pick a winner.
Let’s check out of the meat and potatoes of the contract, the
payable in the function definition. The key here is
transfer, which takes the payout for the winning team (calculated with
this.balance / teamName.length), and
transfers an even amount to each player.
Let’s check out the
This cycles through the list of players in the winning team and
transfers the payout equally (
this.balance / teamName.length) and sets the
playerIndex. Solidity doesn’t allow you to compare two strings natively, so I had to create a function to do that.
Finally, let’s take a look at the
Just in case, ya know?
delete essentially resets those address arrays if I wanted to try again.
That’s basically it. The next challenge was to build a React app that talked to the blockchain and interacted with the contract. Here’s what it looks like before entering:
playerIndex is 0 still
And when you click the “enter” button:
Rinkeby is a test network for Ethereum.
The app uses Metamask, which is a Chrome extension to let you interact with the Ethereum blockchain in your browser. Think of it as a wallet you can use on websites. Once the transaction is submitted, you have to wait a little while (20–30 seconds) for the miners to confirm the transaction. Once there are block confirmations, you’ll get back a transaction hash. Here’s the one I got back when I took this screenshot.
When you refresh the page (I know), you should see that you’re entered:
manager variable above? When I switch back to the original Metamask account that I deployed the contract with, I can see a special Manager Tools section:
It’s tempting to never use the middle button.
Let’s see what the page looks like when I pick a winner:
Now the payouts are zero’d out and I noticed some extra ETH in my account. It would have been cool to show the final payout, but I didn’t have time.
It’s crazy to think this website doesn’t have a database; it relies on the contract’s data changing when people enter or pick a winner.
It was awesome learning about dApps and contracts, and I hope to keep building more.
By the way, the Big Game contract is deployed to the main Ethereum network now.
If you want to check out the full contract, check out the Github repo.
If you’re interested in the tech stack, I used:
- React for components (create-react-app)
- Bulma for CSS framework
- Redux for data layer (reduxForm was considered)
- Mocha and granache for testing (also Remix)
- web3 library with Infura hosts for talking with the Ethereum network
- Docker for containerization
- Zeit’s Now for deployments
If you want to see any of the web page source, hit me up on Twitter!