App Rules and Blockchain Setup
This is the first part of a series on building decentralized applications using the Ethereum blockchain.
We’re going to build 3 things:
- a custom token
- a DAO which uses the tokens as votes
- a prototype web UI for interacting with the smart contracts
After following the instructions in this book, you’ll be able to build your own custom Ethereum token with or without an accompanying DAO and app.
What We’ll Be Building
The project we’re building is called The Neverending Story (TNS). The full project can be found at storydao.bitfalls.com. Its full code is on GitHub.
The Neverending Story is a web application with input fields (text and image) where users who have MetaMask installed can send in a paragraph of text or an image, depending on certain conditions. (The image only appears once every 50 paragraphs and can only be a URL.)
The full story is rendered next to the input fields. The more entries that exist in the story, the more expensive it is to submit an entry. Submitting an entry is an action available to everyone who pays the fee, is whitelisted, and has at least one TNS token.
Action types:
- Submit entry: requires the sender to have at least 1 TNS token and be in the whitelist (see below). Costs
0.0001 ether * number of entries in current chapter
(see the “Chapters” section below). This can be image only once per 50 text entries and can only be a URL. Otherwise it’s text. No code, plain text only. In either case, text field size limit is 256 characters. - Transfer ownership [Owner only]: can transfer ownership to a new address.
- Reduce fee [Owner only]: the owner can make the fee to submit entries (see the “Fees” section below) lower without asking for a vote.
- Buy TNS Tokens: send ether to the DAO to get a proportionate amount of TNS tokens automatically sent back. If there aren’t enough TNS tokens in the DAO, you must obtain them from an exchange instead.
- Check token balance: a read-only action which checks how many TNS tokens there are in the DAO.
- Whitelist: this function is auto-called when ether is sent to the DAO’s address. It notes the sender in a whitelist array for future reference so that people who acquire a lot of TNS can’t just distribute them to various accounts.
- End Chapter: triggers the chapter end process for distributing Ether dividends and resetting the entry fee.
- Withdraw: called when stakeholders want to withdraw their dividend.
- Owner Withdraw [Owner only]: called by Owner to withdraw fee earnings.
Stakeholders (TNS token holders) will be able to vote on proposals, and any proposal reaching more “YES” votes than “NO” votes will get approved. The number of votes does not matter; the ratio matters. Proposals need to be open for votes for a given period of time, depending on type of proposal.
Proposal types:
- Remove entry: when confirmed by vote, the target entry is removed. Voting time: 48 hours.
- Emergency remove entry [Only Owner]: can only be triggered by Owner. When confirmed by vote, the target entry is removed. Voting time: 12 hours.
- Emergency remove image [Only Owner]: only applies to image entries. Can only be triggered by Owner. When confirmed by vote, the target entry is removed. Voting time: 4 hours.
Later on we can add other types of proposals using the same method.
The proposals all need to be clearly listed somewhere in the UI of course, so that people know their votes are needed. A voter needs only one TNS token to be able to vote, but the more tokens they have the more their vote is worth.
Tokens Are Locked During a Vote
A user’s tokens are locked during a vote. That prevents a whale TNS holder from overpowering every active vote. The voters will have to distribute their voting power on votes that matter to them.
Chapters
After 1000 entries or three weeks of time, a chapter’s end can be called by any user. The DAO will then distribute collected ether to all TNS holders, proportionate to their balance. A holder does not need to be whitelisted in the DAO to get dividend ether. They only need to hold TNS tokens at the moment of distribution.
The distribution is a pull-mechanism: the holders need to call the withdraw function of the DAO to get their ether. It will not be automatically called. The withdrawal window is 72 hours. 50% of the unclaimed ether goes to the owner, while 50% goes into the next chapter’s dividend.
Fees
1% of every submitted entry fee goes to the current Owner. The rest is put into a pool and distributed to all TNS holders after every chapter ends, proportionate to their TNS holdings.
The Owner’s fees go into a separate balance from which they can periodically withdraw at will.
To get whitelisted, the user must send 0.01 ether to the DAO. All future purchases of tokens are at a much lower price. The 0.01 ether entry fee is there to prevent Sybil attacks. If the user sends more than 0.01 in the first go, the 0.01 go towards the whitelisting, while the leftovers will be used to calculate how much more TNS the user gets. All tokens will be sent back to the user in one go.
In a nutshell, think of this project as a crowdsourced choose-your-own-adventure story with crowd curation and community censorship. A story-DAO.
Bootstrapping: PoA Private Blockchain
We’ll do two bootstrapping procedures: this one will focus on running our own real Ethereum blockchain locally. It will use Proof of Authority as a consensus mechanism, and function as any real Ethereum testnet would.
- Download and install Virtualbox.
- Download and install Vagrant. If you’re not sure what virtual machines are, please see this post.
- Download Geth from here. Be sure to scroll down and download “Geth & Tools”, not just “Geth”. If you’re on macOS, you can also use Homebrew and install it with
brew install ethereum
. - Mist can be downloaded here. Be sure to download “Mist” and not “Ethereum Wallet”. Mist is the Ethereum “browser” which can open various DApps. Ethereum Wallet is the same thing, but locked into wallet-mode, so you can’t open other apps with it. This is to prevent non-technical users from visiting malicious DApps.
Mist and Geth
If you’re curious, learn more about Mist and Geth here.
We need VirtualBox and Vagrant because we’ll be using this approach to launch two virtual machines on which our nodes will be running, simulating two computers running an Ethereum node.
Next, follow the instructions from this post to get a PoA private blockchain set up.
You’ll end up with two running nodes. Each will be mining to its own address. Make a note of those addresses. Mine were:
- Node1:
0x4b61dc81fe382068e459444e8beed1aab9940e3b
- Node2:
0x97e01610f1c4f4367c326ed1e9c41896b4378458
Bootstrapping: Ganache CLI
The second type of bootstrapping we can approach, and this is particularly useful for testing our contracts, is Ganache CLI, previously known as Testrpc.
Ganache is a JavaScript-based blockchain simulation running locally. It re-runs the blockchain from scratch every time we run tests or relaunch our app. This helps us test edge cases quickly but doesn’t lend itself well to long-term testing of long-lasting contracts.
First, install Ganache with npm install -g ganache-cli
.
Then, simply run ganache-cli
and you’re ready. You should see output similar to this one:
$ ganache-cliGanache CLI v6.1.0 (ganache-core: 2.1.0)(node:40584) ExperimentalWarning: The fs.promises API is experimental
Available Accounts==================(0) 0xa0b7139a36ecda5ffda66b9cf97cb9de36e63f2f(1) 0x1f5546797a0ff7efe42ecafaeebd5c932f1a0143(2) 0x0eacbad38a642db2204574ad01b2b51c82ff7080(3) 0x77f40a8add69b0e0806c0c506208e5783b89076d(4) 0x1ea41547984ecb949c2b2df311bffe0fdeae4632(5) 0xa1ad154fd5fd11ebe5410c992e5e97b461c516a2(6) 0x34da52fd90c015a41bcc383ba3d804f7cebbc84e(7) 0xddd5232788c1f1192d6ac5e82e74ca80945e119e(8) 0x7ebc838124a676eac57f9b6275cd29b1a1c63d4d(9) 0x6feed7913319ffb1b01f767960dd843ea7f96181
Private Keys==================(0) 62727ad35a288eb34f268cffb1ce620ef3ee80910138aed0e81f24d912fd8a49(1) a6c76b382c655dcc66dd92428e3e0a0f14b7458162ad8e5cbbbcc64d3362d28c(2) eef05f81fd995329c80d8875d5cb62b81f8f28c39951665b4b15688dc48b4c47(3) 5ae06fc34da5d47a64a814ee088f7c6f0d1cae3c63d7ad2d6b71b8128bce1764(4) 8cc43f28054f90243dea496263bd9a45f33db44ea3956ab8d0e8704e15d0787e(5) dcf37436237105ea2f5b1be608b6aa1fe6fb7ca80b8b23ce01ff96930a2a3045(6) f896b6f0ee11ea272c1567ec1950f7ff610df79193cbb7b668ae0ea11f6ec825(7) 877b5868dca9a2f5c7d9546647171c9825f1b02922442f18dd4e90d108b9e54d(8) 7f1f3515d71d348a78ae85a755e02df49be4e0b374447b822abe5a6481fe0c58(9) 20d50b28c8b051406edc6aa61becc3443e430d7d68925a108958f8abecd55ed3
HD Wallet==================Mnemonic: soda tower talk dynamic swim tattoo edit cook pair bid glance beautyBase HD Path: m/44'/60'/0'/0/{account_index}
Listening on localhost:8545
What Ganache is doing here is starting a private blockchain with virtually no mining time and no nodes. It executes transactions as soon as they come in. It’s also generating 10 addresses pre-loaded with a lot of virtual ether, and spitting out their private keys so you can import them into various tools like MetaMask, MyEtherWallet, or the previously downloaded Mist.
We’ll be using a mix of this method and the method above, depending on our needs, so make sure you set up both.
Ganache UI
Preferably and alternatively, use the Ganache UI tool to have a visual interface for managing your Ganache blockchain.
Conclusion
Use this guide to connect to the private blockchain (either version) with tools like MetaMask, MyEtherWallet, or the previously downloaded Mist. Both bootstrapping options, when running, run on localhost:8545
by default, so the process of connecting to them is identical.
Now that our app’s rules and features are laid out and our private blockchain is set up and we can connect to it, let’s focus on tools, packages, and dependencies next.