Background
Cryptocurrencies have been around for almost 10 years, the first being the most famous - Bitcoin. Cryptocurrencies have the potential to disrupt almost all industries where value is passed between two parties via a third, as they offer the ability to replace expensive trusted intermediaries with inexpensive software-based algorithms that enforce the transfer of value when predefined conditions are met. Banking fees are replaced by mining fees, which can reduce costs.
Ethereum shares many properties with Bitcoin, but also comprises a Turing-complete distributed computer system called the Ethereum Virtual Machine (EVM). Ethereum’s killer feature is smart contracts; smart contracts are stateful, and execution of functions exposed by the contract changes the state of the contract. Value being transferred between two parties is an example of such a change of state; online voting is another.
Smart contracts are usually written in a language called Solidity, which is compiled to bytecode; the contract is then deployed to the EVM and its functionality can be invoked by anyone with an Ethereum address. Anyone can also deploy smart contracts to the EVM (at a cost), so the system is also permssionless (i.e. open to everyone).
ERC 20 tokens
In this document I am going to show how easy it is to create a very basic cryptocurrency. We’ll call this the GPasToken. This will be an ERC 20 token written in Solidity and deployed to a local blockchain to ensure correct functionality. We’ll also show how to test our contract to ensure our implementation is correct. We will use several tools and libraries to make things easier.
ERC 20 tokens (or cryptocurrencies) are nothing more than smart contracts that conform to a predefined interface; most of the best-known Ethereum-based cryptocurrencies implement the ERC 20 interface.
This exercise was carried out on a Mac; some steps may differ slightly for Windows.
Getting Started
First lets create a folder for our new project:
mkdir GPasToken
cd GPasToken
Now we introduce a framework that allows us to build, test and deploy our smart contracts, and a library to ensure our tokens are secure and ERC 20 compliant. The framework we’ll use is called Truffle. We will also use a library with some predefined contract templates, called OpenZeppelin. We inherit from the contract most closely matching the problem at hand, in this case the creation of new digital tokens is a solved problem so we won’t reinvent any wheels here.
To install Truffle globally using npm, and setup your project, run these commands in a terminal window:
npm i -g truffle
truffle init
npm init -y
npm i --save truffle
Finally install OpenZeppelin using npm:
npm install -E openzeppelin-solidity
Creating an ERC 20 Token
If you drill into node_modules/openzeppelin-solidity/token/ERC20
you will find several templates you can use for your smart contract. These are all ERC 20 compliant, and using them is as simple as inheriting from your preferred contract template. Lets create GPasToken.sol
and add the required code for our smart contract.
Create the contract using touch contracts/GPasToken.sol
, and then open the resulting file and add this code…
pragma solidity ^0.4.24;import "openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol";contract GPasToken is BasicToken {
string public constant name = "GPas Token";
string public constant symbol = "GPAS";
uint8 public constant decimals = 0;
uint constant INITIAL_SUPPLY = 5000000; constructor () public {
totalSupply_ = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
}
}
BasicToken
(and the base contracts that it inherits from) implements most of the functionality we need, we just define a name, symbol, supply, and number of decimals (I’ve chosen 0, but many ERC 20 tokens use 18 decimal places; this is a matter of personal preference). An example of the code being implemented within BasicToken is given below:
contract BasicToken is ERC20Basic {
...
mapping(address => uint256) internal balances;
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}
...
}
Code also exists within the base contracts to handle transfers and so on. If you’re drawing analogy with traditional programming, imagine a single instance of a class running on your computer, each invocation of a function potentially changing the state of the object. In this case the contract is the class and each invocation of a function is a transaction on the Ethereum blockchain (with the order of each call to a function on the contract managed by the blockchain ledger).
Testing
With our contract in place we add a test file using touch test/GPasTokenTest.sol
, and some code to test our contract…
pragma solidity ^0.4.24;import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import '../contracts/GPasToken.sol';contract GPasTokenTest {
function testEnsureTokenNameIsCorrect() public {
GPasToken token = GPasToken(DeployedAddresses.GPasToken());
string memory expected = "GPas Token";
string memory actual = token.name();
Assert.equal(actual, expected, "Ensure token name is correct");
} function testEnsureTotalSupplyIs5Million() public {
GPasToken token = GPasToken(DeployedAddresses.GPasToken());
uint256 expected = 5000000;
uint256 actual = token.totalSupply();
Assert.equal(actual, expected, "Ensure total supply is correct");
} function testEnsureSymbolIsCorrect() public {
GPasToken token = GPasToken(DeployedAddresses.GPasToken());
string memory expected = "GPAS";
string memory actual = token.symbol();
Assert.equal(actual, expected, "Ensure symbol is correct");
} function testEnsure0Decimals() public {
GPasToken token = GPasToken(DeployedAddresses.GPasToken());
uint256 expected = 0;
uint256 actual = token.decimals();
Assert.equal(actual, expected, "Ensure 0 decimals");
}
}
Ensure that test names are prefixed with the word test
. The tests aren’t doing anything especially interesting, but should adequately demonstrate how to write a basic test.
Deployment
To ensure the contract is deployed, first run this command…
touch migrations/2_deploy_contracts.js
…then add this code to the resulting file…
var GPasToken = artifacts.require("./GPasToken.sol");module.exports = function(deployer) {
deployer.deploy(GPasToken);
};
We’re now going to use another tool from the Truffle suite called ganache-cli
, which is basically an Ethereum node running on our own machine; this allows us to deploy smart contracts to our own local blockchain so we don’t need to use real Ether! Ganache can be installed globally with npm using this command (a GUI tool is also available if you prefer):
npm i -g ganache-cli
Run Ganache by typing ganache-cli
into the terminal. You should see it has generated 10 accounts, complete with private keys, each funded with 100 Ether.
We need to tell Truffle to deploy our contract to our Ganache instance, and we can do this by editing truffle.js (or truffle-config.js for Windows) to point to the right location:
module.exports = {
networks:{
development: {
host:'localhost',
port: 8545,
network_id: "5777"
}
}
};
To ensure the contract is compiled, run truffle compile
from the root of the project, and then truffle migrate
to deploy. Make a note of the contract ID, the output will look something like this:
GPasToken: 0xfe724d8e61ffec437b0432fbb365bf8e051fd2cd
The contract ID is the 0x… part.
You’ve now deployed your own digital tokens to your local Ganache instance.
View your tokens
You can view your tokens using any ERC 20 wallet that can be pointed to a localhost testnet. I use MyEtherWallet, which is an online service. In the top right of the homepage there should be a drop down where you can choose which network to connect to. Select Custom and enter localhost
and the port of your Ganache instance (ganache-cli is 8545
by default). Now import your wallet using View Wallet Info and enter the private key of the first address your Ganache instance generated. You can now add custom tokens (in this case use the symbol GPAS
) and verify your balance.
Conclusion
There is still a lot of hype around cryptocurrencies, despite the recent decline in the price of cryptocurrencies such as Bitcoin and Ethereum. In this example I showed how, with just a few dozen lines of code, digital tokens can be created and deployed to the Ethereum network.