Introducing TheButton.co — a Simple Ethereum Game

TL; DR

This is a take on the popular Reddit experiment the button, but with a few key differences. At the core, this button is based on an Ethereum smart contract. There’s a countdown timer — when the button is pressed the timer resets (just like the original). Anyone can press the button as many times as they want, but it costs ether to press it. The last presser wins the accumulated ether as a jackpot!

Check it out here and join our subreddit!

Detailed Description

Rules of the game

The above TL; DR is a huge oversimplification, because it only scratches the surface. Firstly, funds deposited by pressing the button go into four distinctive “buckets”:

  • Jackpot (currently 85%)
  • Charity (currently 5%)
  • Revenue for the devs (currently 9%)
  • The rest goes to the next campaign (currently 1%)

As can be inferred, if the timer runs out, a campaign is finished. When that happens, the next button press will finalize that last campaign, and it will start a new one. Finalizing a campaign means that the accumulated ether will be split according to the pre-set fractions as described above.

Secondly, the price for pressing the button is not constant! There are two parameters which determine how the price changes: N, and the price multiplier. Currently N = 5, and the price multiplier is set to 6%, which means that the price will increase by 6% every 4 presses.

Lastly, a campaign has one more parameter that determines its behavior — the period (or what the timer resets to), which is currently set to 30 minutes.

Motivation

If you’re familiar with the original button, then most of this will make sense, but if not, I highly recommend checking out the original subreddit. I’ve been learning solidity for the past year and I had been thinking about some simple and fun ideas which I could implement as dApps. Thinking about past simple and viral internet phenomena I quickly connected the dots and thought about how the button can be made into an Ethereum dApp. I’ve never done any web development before, so it was a major learning experience!

I have engineering background, but I’ve also just finished an MBA. I’ve been thinking a lot about what smart contracts can do for businesses, and my Accounting smart contract base is one of the ways I hope to contribute to developers and companies who intend to base their business on smart contracts. Another direction, which I hope more blockchain projects take and which I would like to contribute to, is thinking about giving back to society. We’re all obsessed with the technology we’re developing, or the prices of crypto and tokens we’ve bought, but not many of us have stopped to appreciate what we have, and to think about how we can help the disadvantaged in the world. This is why I’ve implemented a charity fraction in the button dApp, and I intend to add this to any future dApp projects I work on. Thinking about CSR is not only for already successful companies, I think it can be part of very young ventures as well (that topic can be a whole separate article on its own)!

The current charity beneficiary is Giveth.io — I have no association with them whatsoever. They are working on developing the future of giving on the Ethereum blockchain, and are one of the few charitable organizations that accept ETH as donations currently. They are completely transparent about how they spend their funding and will make it easy to donate to specific causes in the future.

Smart Contract Overview

For those of you who want to understand exactly what the smart contract does, I will explain it step by step here. The contract is deployed here

There’s ButtonBase contract which contains all simple getters and setters and TheButton which contains the core logic. The base contract inherits DSAuth for ownership and Accounting for accounting. Also using DSMath for safe math.

A button campaign is contained in a struct:

Button Campaign Struct

All of the campaign parameters can be changed, but changing them only affects the next campaign, as the parameters are stored separately as internal variables. Parameters can be changed by the owner of the contract, but only to a certain extent, using these function modifiers:

Limiting Function Modifiers

The limited modifier ensures that some supplied argument has hard-coded limits and the timeLimitedone ensures that a function can only be called once in a while— useful when setting the button parameters or accounting fractions:

Changing Accounting Parameters

Setting the charity beneficiary is also timeLimited — this does not by any means prevent the devs to cheat and steal the charity funds (by waiting out the period for setting the beneficiary), but it at least guarantees that we can’t do it whenever we want. We have no interest in cheating anyone out of their hard earned money, but we need some time to gain legitimacy and the trust of the community.

Winners’ funds are kept in a mapping:

mapping (address => Account) winners;

Withdrawing the jackpot is as easy as (using the proprietary accounting functions makes it easy to handle value):

Jackpot Withdrawal Function

Sending charity ETH:

Donation Function

Since the Accounting base keeps track of all known deposits and withdrawals, we have functions to redeem any surplus ETH (can be sent from a contract selfdestruct) or ERC20 tokens:

The main contract contains the press logic:

Button Press Code

Which boils down to this:

Button Press Logic

The button can be stopped, but that only prevents from starting a new campaign, and does not affect any running campaign. It also prevents from finalizing a campaign from the press function, that’s why there is a separate public finalize function that allows anyone to finalize the last campaign.

Handling a press looks like this:

Press Handling — Internal Function

Starting a new campaign:

New Campaign — Internal Function

Finalizing a campaign:

Finalizing a Campaign — Internal Function

Working with DSMath makes it easy — it can treat numbers as wads (numbers with 18 decimal places), so if a fraction is set to 0.05*10¹⁸ (5% in wad), it’s a matter of multiplying the total balance with that fraction using the wmul function to figure out how much to transfer to the given account.

For more, check out the official smart contract code verified on Etherscan.