If you haven’t read Part-1, go read it first and this will make more sense. This tutorial isn’t going to teach you everything in detail, this is more about getting straight to the point and to give you just enough information to get things done. Also we will try and stick as much as possible to the standard/popular way of developing DApps, so that it might be easier for you to search on Google or for that matter ask help from other experienced DApp developers.
If you come from a field of Research or have a background in software engineering, you might notice that Blockchain based technologies usually have names that have little to no relation to what they actually do, each name just sounds cooler than the previous one, but they are inherently very simple technologies, so let us first try and breakdown each of those words in the title:
Smart Contracts: You can assume these to be a set of instructions or a program, once deployed to the blockchain can never be changed.
so are these just read-only non-upgradable programs? Yes that’s it! but with one major difference, normal programs don’t cost you anything for writing to a permanent storage like a Disk or Database but in the world of Smart Contracts, the block chain itself is the permanent storage and any writes to it will cost you money(or gas) though Reads are free 🙂
Note: As with anything, there are exceptions and there are ways and means of making a contract upgradable, we won’t cover it here as it would just increase the scope of this tutorial.
Solidity: Similar to how Java targets the JVM, or how Rust/C++ target x86/ARM hardware, Solidity targets the EVM(Ethereum Virtual Machine), Solidity is just one of the languages that target the EVM but it’s the most popular one.
If you are coming from a curly brace language like I did, it might look similar at first glance and they do say it is influenced by C++, Python and JavaScript, but you might spend the first few hours cursing and pulling your hair at why everything is laid out so differently. I highly recommend this interactive free course if you want to learn all about the little details of the language.
Truffle: Just like how Webpack is to the world of Javascript, or how Gradle/Maven is to the world of Java, Similarly Truffle is a framework for Solidity that provides you with some structure and starter code with some nice features to test and deploy your Smart Contracts.
Let us start by installing Truffle, I expect you to have NodeJS installed, if you haven’t, do yourself a favor and install NodeJS using NVM and make sure you choose the LTS version. if you are on Windows, do this from within a WSL distribution.
The following command will install truffle globally
npm install truffle -g
Now let’s go to our home directory and make a folder for project and let us call it ZeroCoin:
cd ~ mkdir ZeroCoin cd ZeroCoin
Let us initialize an empty project using truffle
truffle init
This should give you a structure that looks something like this,
Now let us create a contract contracts/ZeroCoin.sol and before we go about writing our contract, let us go ahead and install openzeppelin in the ZeroCoin directory,
npm install @openzeppelin/contracts
OpenZeppelin is a library for developing secure smart contracts which also include NFTs. It is community-vetted and has been audited by various security firms, so it will provide you with a foundation instead of you having to worry about the little details.
Our contracts/ZeroCoin.sol would look something like this,
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract ZeroCoin is ERC20 { constructor() ERC20("ZeroCoin", "ZERO") { _mint(msg.sender, 1000 * 10 ** decimals()); } }
If you had any experience with a programming language, you will quickly understand that ZeroCoin basically extends the ERC20 contract and ERC20 has most of the functionality to make it work. The initial and max supply of this token is just 1000.
If you notice the 10 ** decimals()
part, it just says 10 to the power of 18, and why do we do this?
Often, you’ll want to be able to divide your tokens into arbitrary amounts: say, if you own 5
ZEROs, you may want to send 1.5 ZEROs
to someone, and keep 3.5 ZEROs
to yourself. Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. You may send 1
or 2
tokens, but not 1.5
.
How can this be solved? It’s actually pretty simple, in our contract we use larger numeric values, so that a balance of 50
will represent 5 ZEROs
, a transfer of 15
will correspond to 1.5 ZEROs
being sent, and so on.
Now let us go ahead and compile our contract,
truffle compile Compiling your contracts… Compiling ./contracts/Migrations.sol Compiling ./contracts/ZeroCoin.sol Compiling @openzeppelin/contracts/token/ERC20/ERC20.sol @openzeppelin/contracts/token/ERC20/ERC20.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.5.16+commit.9c3226ce.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version pragma solidity ^0.8.0; ^---------------------^ Error: Truffle is currently using solc 0.5.16, but one or more of your contracts specify "pragma solidity ^0.8.0". Please update your truffle config or pragma statement(s).
This is something that you too would likely face, Truffle is known to ship with itself an ancient version of the Solidity compiler that is eons behind what OpenZeppelin requires, to get around this, we first get the list of the latest compilers from the solidity project,
truffle compile --list
✔ Fetching solc version list from solc-bin. Attempt #1
[
"0.8.6",
"0.8.5",
"0.8.4",
"0.8.3",
".. and 79 more. Use --all
to see full list."
]
at the time of writing, 0.8.6 is the latest version, you can also get the latest version from the releases section of their Github repository. Now we specify this version in our compilers
section within the truffle-config.js
file as shown below,
compilers: { solc: { version: "0.8.6", } },
Now if you compile, it should compile everything successfully and you should see a build
folder with your compiled contracts.
truffle compile Compiling your contracts… Compiling ./contracts/Migrations.sol Compiling ./contracts/ZeroCoin.sol Compiling @openzeppelin/contracts/token/ERC20/ERC20.sol Compiling @openzeppelin/contracts/token/ERC20/IERC20.sol Compiling @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol Compiling @openzeppelin/contracts/utils/Context.sol Artifacts written to /home/silva/ZeroCoin/build/contracts Compiled successfully using: solc: 0.8.6+commit.11564f7e.Emscripten.clang
Now let us try and deploy our contract to the Harmony TestNet using Truffle. To do this, we need some kind of local wallet, so we go ahead and install a package that allows us to act as a wallet,
npm install --save-dev @truffle/hdwallet-provider
Now we modify our truffle-config.js
file as shown below, make sure you put your own mnemonic that you go from the Part 1 of the tutorial.
const HDWalletProvider = require('@truffle/hdwallet-provider'); const mnemonic = '<ADD-YOUR-MNEMONIC-HERE>'; module.exports = { networks: { testnet: { provider: () => { return new HDWalletProvider({ mnemonic, providerOrUrl: 'https://api.s0.b.hmny.io', // https://api.s0.t.hmny.io for mainnet derivationPath: `m/44'/1023'/0'/0/` }); }, network_id: 1666700000, // 1666600000 for mainnet },
Now we are ready to deploy it to the testNet
truffle deploy --network testnet Compiling your contracts… Everything is up to date, there is nothing to compile. Starting migrations… Network name: 'testnet' Network id: 1666700000 Block gas limit: 80000000 (0x4c4b400) 1_initial_migration.js Deploying 'Migrations' transaction hash: 0xaba3924385a3b8268ac373d826ff35cf35563136bd3b6ba59db94c8ee4f6d2e3 Blocks: 2 Seconds: 4 contract address: 0x72a378d189043F98D178d5Eb0460ad29741A6a22 block number: 12082366 block timestamp: 1625920978 account: 0xBAEA7ac8316C40d4aE2caB7306DaB369aF990cC0 balance: 10100.99751146 gas used: 248854 (0x3cc16) gas price: 10 gwei value sent: 0 ETH total cost: 0.00248854 ETH Saving migration to chain. Saving artifacts Total cost: 0.00248854 ETH Summary Total deployments: 1 Final cost: 0.00248854 ETH
The important part to note down here is the Contract address and then you can add it to Metamask and use it to send and receive your token.
Also, If you need your private keys for whatever reason, you can use the following command,
./hmy keys export-private-key <ACCOUNT_NAME> --passphrase
In the next tutorial, I will try to focus on creating a simple DApp that interacts with the token that we just deployed. If you have some feedback or feel like you are stuck anywhere, feel free to message me on reddit and I will try my best to help you out.
If you found this useful and feel like supporting me, here is my public ONE address 🙂
Address: 0xeb5Ca70f9B2e852C1Fc74a9Fc12CA93679d3Bae4 ONE Style Address: one1adw2wrum96zjc878f20uzt9fxeua8whyacpf9t
do send me a message if you send ONEs, I’ll add your names to the list of contributors in the upcoming tutorial 🙂
Thanks to:
- /u/OG_Lemurman (for the tips in ONE)