Create your family’s chore token in Ethereum
In this story, I will show how I created my family's virtual chore token in to live in the Ethereum blockchain, there are two reasons why I created mine, 1) learn more about Ethereum and smart contracts, 2) pay our kids with AguilaCoin instead of fiat — AguilaCoin is the name of our coin, start thinking about your token name!
A few notes:
* In this post I use token and coin interchangeably to refer to ERC-20 Token.
* Screenshots are from my mac instead of raspberry pi.
Index
- Setup a private Ethereum node(s).
- Create individual wallet addresses.
- MetaMask as a wallet.
- Create the chore token.
- Deploy the token to your private network.
- Use MetaMask to send tokens.
1. Setup a private Ethereum node(s)
In this tutorial, we’re going to be creating a Clique (proof-of-authority) network because it’s the most efficient for a one node private network compared to Ethash (proof-of-work).
First things first, decide where you want the private Ethereum node to be running 24/7 (I have it running in a Raspberry Pi), you can start by using your personal computer for initial testing.
Next is to download and install Geth, I downloded Geth & tools v1.9.23 armv7 for my Raspberry, here’s the download page for all systems, or detailed instructions on how to do that depending on your operating system, if you have any questions about this please add a comment. Test the installation by running geth --help
.
Before we start creating accounts and configuring the node, create a working directory workspace
and within it create another folder named data
, open the terminal and cd
into workspace
.
Each node that verifies and signs transactions need to be configured with at least one account, for this tutorial I’m going to show how to do that with one node.
From the terminal in the workspace directory, run $ geth account new --datadir data
and give it a strong password, your output should look like the following screenshot:
Next, create the Genesis block, copy, edit and save the below code into a file named genesis.json, I’ll show the code and then I’ll explain the things we’re going to be modifying, if you’re interested to know more about each of the properties klaytn docs has a really good site for that:
{
"config": {
"chainId": 54321,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"clique": {
"period": 0,
"epoch": 30000
}
},
"difficulty": "1",
"gasLimit": "8000000",
"extradata": "0x0000000000000000000000000000000000000000000000000000000000000000db05ce4Ad123B5e63C5D0990158AbE08690DfF8F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"db05ce4Ad123B5e63C5D0990158AbE08690DfF8F": { "balance": "600000000000000000000" }
}
}
chainId
— chain identification number, change this to whatever you like, but don’t pick one that is already used, take a look at chainid.network so that you don’t pick one that is already used.
extradata
— specified who will be signing the transactions, copy the public address from the account you created above and replace my address with yours, make sure there are 64 leading zeros (32 bytes) and 130 zeros (65 bytes) after your address, don’t include the 0x
from your address.
alloc
— specify the allocations of ether per address, in the case above I have allocated 600 Eth (600000000000000000000 wei), you can use gwei.io to learn about Ethereum base units, at the bottom of the site there’s a unit converter.
In addition to the signer address, add your personal address to the alloc
section as well, you’re going to need ether for all transactions, read 2. Create individual wallet addresses section below if you don’t already have one.
After you’re done with the modifications to you genesis block save it to workspace/genesis.json
.
Initialize the blockchain node using the genesis block above by running the following command within your workspace directory:
$ geth init --datadir data genesis.json
To start the node again after creation you just specify the network id as follows:
$ geth --datadir data --networkid 54321
To test that the blockchain is working open another terminal tab or window and open a geth console to run a few commands:
# attach to the node
$ geth attach /path/to/your/data/geth.ipc# get all accounts
> eth.accounts
["0xdb05ce4ad123b5e63c5d0990158abe08690dff8f"]# The above command will only show the signer account address because your personal account doesn't have any transactions yet, but it shows that is working correctly.
You can now type exit
in the console to exit the console and also stop the geth node on the other terminal instance by running Control+C
so you can setup geth as a service with the steps below.
Configure geth to run at startup
There steps worked for me on the Rasperry Pi OS:
- Create a file named
geth.service
within your workspace directory and paste the following:
[Unit]
Description=Ethereum go client
Wants=network-online.target
After=network-online.target[Service]
Type=simple
ExecStart=geth --datadir /path/to/your/data/folder --networkid 54321 --miner.gasprice 0 --unlock 0xdb05ce4Ad123B5e63C5D0990158AbE08690DfF8F --password /path/to/your/password.txt --mine --nodiscover[Install]
WantedBy=default.target
in the above code, specify the full path to your data directory, your network id, the address of the signer address and a path to a file containing the signer account password, save and follow the next steps to add the service to systemctl:
2. Enable the service by running $ sudo systemctl enable geth.service
3. Reload the services by running $sudo systemctl daemon-reload
4. Start the service by running $ sudo systemctl start geth.service
5. Test that the service is working by resting the computer where the node is running and opening a console like you did earlier after restart.
It’s important to note that the above configured node is unlocked with the signer address and anyone that has direct access to this node will be able to execute anything on this node, this is why I’m going to show how to create another node that allows external connections.
Create the member node
This node will be used as the gateway between clients and the signing node, it will expose the APIs used by client aplications.
- Within the workspace directory, create another directory, this time call it
data-client
. - Create an account for this new node, by running
geth account new --datadir data
. - Initialize the node by using the same genesis.json.
4. Get the signing node enode address by running and then stoping the mining node, copy the highlighted text below and paste it into a file named static-nodes.json, save this file under workspace/data-client/static-nodes.json
.
notice that static-nodes.json contains only a json array with only one value, the signing enode address.
5. Start mining by running the following command:
geth --datadir /path/to/your/data-client --networkid 54321 --port 30304 --miner.gasprice 0 --mine --http --http.api eth,net,web3 --http.addr 192.168.0.17 --nodiscover
From the above command, change the http.addr to your node’s local address, also notice that it’s enabling API access through HTTP, eth, net, web3.
6. Test the member node from another computer if you can, make sure that you have properly configured the firewall, but for the purpose of this post let’s test it using the same machine by using the following command to connect to the node using the console: $ geth attach http:192.168.0.17:8545
make sure you use the same local address you specified when starting the member node, localhost or 127.0.0.1 won’t work, also notice the default port for HTTP communication 8545, once you’re attached you can run eth.accounts
to see if it’s sending and receiving communication.
Optional: Expose your private node to the world:
- If you don’t already have an SSL cert, create one using certbot so you can get a free SSL cert from letsencrypt, you’re going to need this if you want to connect externally from wallets, it’s safer this way as well, you don’t want to be sending plain text communication to your node, do you? :)
- Get a free domain from no-ip and configure it to point to your local network.
- Configure your router to forward the 8545 port to the computer running the node.
2. Create individual wallet addresses
For each person that is going to be using your chore coin create a wallet address, there are several options out there to create ethereum addresses, but in this post let’s use iancoleman’s Mnemonic Code Converter, follow the steps described in the picture below screenshot
The text that appears in the BIP32 Mnemonic if your “username and password”, this passphrase is what’s used to generate your public addresses and your private key, so don’t share this with anyone, well unless you’re creating this for someone else, copy and store in a secure place, like in a paper inside a safe or a password manager. You can save this website so you can use it offline.
If you scroll down to the derived addresses you can see which addresses can are generated.
On the left side you see the public addresses, there are the ones you can share with people or applications so they can send you Eth or tokens, I intentionally covered the private keys to show that these are not to be shared with anyone but yourself.
After you create all the accounts for the people you want to use your token (or they have created their own addresses), copy the list into a text file or an address book so that you can send then Eth so they can make transactions in your blockchain and to transfer chore token between each other.
3. MetaMask as a wallet.
After you have created your account(s) and your node, you’re ready to download and install MetaMask either by using the browser extension or the mobile application, in this story I’m going to be using the mobile application because it’s more useful for the use of the token.
- Install Metamask on your phone, in my case I’m using an iPhone.
2. Import your account by selecting [ Import using seed phrase]
3. I recommend selecting show seed phrase if you’re in a safe place.
4. After importing you account select menu on the top left and then Settings
5. Select Networks
6. Add Network
7. Type in your local address and give it a name, don’t forget about the port number and the chain ID.
8. Head to the main screen and pull down to refresh your account, make sure that you’re in your home network and then you should be able to see the ethereum allocation you have set in your genesis block.
Now you can send Eth to the other accounts that are going to be using your chores coin.
MetaMask is the mobile wallet I’m using to send AguilaCoins back and forth with my family.
4. Create the chore token.
They key to creating our own the token is to use an interface that clients understand, this is why we’re going to be using ERC-20 when creating the smart contract for our token, smart contracts are written in a language called Solidity, if you have basic programming skills, you will be able to understand the code snippets shown below, but before we should any code, there are some tools you will need to install if you don’t have them already.
- Install nvm, npm, and node.
# Below are instructions for macOS Big Sur, these tools don't need to be installed on the machine running your node, these are tools required for development and deployment of the smart contract.# Install nvm Node Version Manager
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash# if nvm can't be found when you open a new termianl add the following lines to your ~/.zshrc file
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm# install npm and node
$ nvm install --lts
2. Install truffle globally using npm
$ npm install truffle -g
3. From a terminal, create a working directory, I’m going to use AguilaCoin but you use whatever you’re naming your token, cd into it and run the following command to create the boilerplate required to redloy contracts to real, test and private blockchains:
$ cd AguilaCoin
$ truffle init
The above will generate the following directory structure and files:
contracts
— this is where you will place your smart contracts.
migrations
— this is where you will specify which contracts you want to deploy to blockchains, and set construction values.
test
— this is where you will develop your test scripts in javascript.
truffle-config.js
— this is where you specify the blockchain and credentials for smart contract deployment.
4. Create a file within the contracts directory, I’m going to call it AguilaCoin.sol, but you name it like your coin.
5. Paste the gist below, change return statements within name() and symbol() to return your coin name and symbol, also try to understand what is doing, if you would like to learn more about solidity take a look at docs.soliditylang.org
It’s important to note that I’m assigning $1,000 AguilaCoins to the address that deploys the smart contract, you can change this value in the constructor()
.
6. if you’re using VSCode you can install the Solidity extension for syntax coloring
7. Create a file named 2_contract_migration.js (the “2” prefix in the name is important), and write the code like in the screenshot below, replace “AguilaCoin” with the contract name you specified in the smart contract, for me its contract AguilaCoin {}
8. Compile your contract to make sure there aren’t any errors, from the same directory you ran truffle init
, now run truffle compile
, you should get an output like the following
$ truffle compileCompiling your contracts...
===========================
> Compiling ./contracts/AguilaCoin.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /Users/sal/Downloads/AguilaCoin/build/contracts
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
5. Deploy the token to your private network.
For this step you’re going to need the mnemonic seed phrase for the account you added on the genesis block, or any account you sent Eth to.
From the same directory where you ran truffle to compile, run npm install @truffle/hdwallet-provider --save
to install a module that knows how to deploy contracts using your account.
Open truffle-config.js
and uncomment the following lines and paster yous mnemonic seed phrase to the const mnemonic
constant, if you’re pushing this to a repository erase the mnemonic before pushing it, another way to do this is by storing your mnemonic in a text file and telling truffle-config.js to read it from there, but don’t commit this file.
Scroll down and find the private configuration, uncomment it and modify it to match your node’s IP address and network id, take a look at my configuration below for reference, note that I added an extra parameter gasPrice
I added this so it doesn’t cost to deploy the contract.
Now you’re ready to deploy your chore token to your private network!
Run the following command truffle migrate --network private
to migrate, you should see something like the following if it was successful:
$ truffle migrate --network privateCompiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.Migrations dry-run (simulation)
===============================
> Network name: 'private-fork'
> Network id: 54321
> Block gas limit: 8000000 (0x7a1200)1_initial_migration.js
======================Deploying 'Migrations'
----------------------
> block number: 2
> block timestamp: 1606795337
> account: 0xE34fcd8eE336c659130B2031756E03cc1c51D8bD
> balance: 599.999646138
> gas used: 176931 (0x2b323)
> gas price: 2 gwei
> value sent: 0 ETH
> total cost: 0.000353862 ETH
-------------------------------------
> Total cost: 0.000353862 ETH2_contract_migration.js
=======================
Deploying 'AguilaCoin'
----------------------
> block number: 4
> block timestamp: 1606795337
> account: 0xE34fcd8eE336c659130B2031756E03cc1c51D8bD
> balance: 599.998237616
> gas used: 676923 (0xa543b)
> gas price: 2 gwei
> value sent: 0 ETH
> total cost: 0.001353846 ETH
-------------------------------------
> Total cost: 0.001353846 ETHSummary
=======
> Total deployments: 2
> Final cost: 0.001707708 ETHStarting migrations...
======================
> Network name: 'private'
> Network id: 54321
> Block gas limit: 8000000 (0x7a1200)1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0xc88636fcc9ca479346e67d9d3ac5a70ec5c79c51d38d49279822f0ee927aaca1
> Blocks: 0 Seconds: 0
> contract address: 0xCf565fC92078E41E0e59d47e14Fd31059f970870
> block number: 2
> block timestamp: 1606795338
> account: 0xE34fcd8eE336c659130B2031756E03cc1c51D8bD
> balance: 600
> gas used: 221491 (0x36133)
> gas price: 0 gwei
> value sent: 0 ETH
> total cost: 0 ETH> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0 ETH2_contract_migration.js
=======================Deploying 'AguilaCoin'
----------------------
> transaction hash: 0x01ab8fd376fd128a8f1e76a3a544107d2269d12da7158a2d0bc574753686cec1
> Blocks: 0 Seconds: 0
> contract address: 0x78045670db9137e65cefADe25bDd18F789c12B0b
> block number: 4
> block timestamp: 1606795339
> account: 0xE34fcd8eE336c659130B2031756E03cc1c51D8bD
> balance: 600
> gas used: 862191 (0xd27ef)
> gas price: 0 gwei
> value sent: 0 ETH
> total cost: 0 ETH> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0 ETHSummary
=======
> Total deployments: 2
> Final cost: 0 ETH
Success!
Now that the smart contract has been published to the private ethereum blokchain let’s use MetaMask.
In the above output, I have put in bold the smart contract address, copy your own contract address, you’re going to need this in the following section.
6. Use MetaMask to send tokens.
Using the account you used to deploy the contract, add the smart contract address by following the next steps
Click [ Add Token ]
Select the custom token tab
Paste your contract/token address to the first field, the token symbol and precision should autopopulate, then click [ AD TOKEN ]
Your token should now show in the main screen, select it to send some chore coins to another account.
Click send (from another device using another account select receive).
Scan or type in the address you’re sending money to, add it to your address book so you don’t have to do this every time, then press [ Next ]
Type in the amount you want to send and press [ Next ], note that (AC) is selected, you should see your own coin symbol selected here.
Check that everything looks good, because MetaMask is created for main or test ethereum networks it doesn’t allow to set 0 network fee, it allowed it at some point but they remove it ever since, this is why we have allocated 600 Eth to our accounts in the genesis block.
After you press [ Send ] it can take a few second for the transaction to confirm, after is has confirmed you’re going to see the transaction as confirmed as shown below and your new balance.
And that’s it, I hope you have enjoy reading and following along as much as I enjoyed writing this for for y’all and my future me!
See ya later ✌️
References
- https://geth.ethereum.org/docs/interface/private-network
- https://docs.klaytn.com/node/service-chain/references/genesis
- https://chainid.network/
- https://geth.ethereum.org/downloads/
- https://gwei.io/
- https://iancoleman.io/bip39/
- https://ethereum.stackexchange.com/a/371/64478
- https://serverfault.com/a/941431/600531
- https://geth.ethereum.org/docs/interface/javascript-console
- https://eips.ethereum.org/EIPS/eip-20
- https://www.trufflesuite.com/truffle