Welcome to a new series about working with the Embark framework. We’ll assume you have a basic grasp on programming and that you’ve read some of our basic explainers or tutorials, in particular the intro to Ethereum or even the Raffle-building tutorial for Ethereum.


Embark is a set of tools for developing decentralized apps on the Ethereum blockchain. It’s an alternative to Truffle and comes with a variety of addons like out-of-the-box integration with IPFS and ENS, a ReactJS-based web app template, and more.

Embark popped into existence some 3 years ago and was relatively recently acquired by Status who are now funding its development and growing its ecosystem.

This tutorial will show you how to get started with a simple smart contract for a custom token on Embark.

Installation

For the purpose of this tutorial, we’ll assume you’re running a *nix based operating system like OS X or a flavor of Linux. If you aren’t, we recommend downloading Git Tools which include Git Bash and thus emulate a Linux terminal rather well. Another approach is downloading and running a simple and effective virtual machine like Homestead Improved.

The prerequisites for running Embark are having an up to date version of NodeJS, IPFS and Geth. Because of the general brokenness of NodeJS, we recommend using NVM to be able to run multiple versions of NodeJS at the same time if necessary. You can install NVM by running the following commands:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
nvm install --lts
nvm use --lts

Note: there’s no official NVM for Windows – alternatives are nvm-windows and nodist.

Instructions for installing IPFS are here.

Instructions for installing Geth are here.

After having installed all the necessary tools, check if they’re functioning by printing their versions. All versions should be equal to or newer than the ones in the screen below.

Versions

Then, we download Embark.

npm -g install embark

After that, we run the initialization command in the folder where our project will be residing.

embark new tokentutorial
cd tokentutorial

Finally, by running embark run we’ll launch the Embark Dashboard.

Configuration

In the config folder, we’ll find configuration variables for different parts of the project. What we need right now is the config/contracts.js file. This file lets us define certain attributes of our environment which will influence the contract deployment process. This code currently looks like this:

module.exports = {
  // default applies to all environments
  default: {
    // Blockchain node to deploy the contracts
    deployment: {
      host: "localhost", // Host of the blockchain node
      port: 8545, // Port of the blockchain node
      type: "rpc" // Type of connection (ws or rpc),
    },
    dappConnection: [
      "$WEB3",  // uses pre existing web3 object if available (e.g in Mist)
      "ws://localhost:8546",
      "http://localhost:8545"
    ],
    gas: "auto",
    contracts: {
      // example:
      //SimpleStorage: {
      //  args: [ 100 ]
      //}
    }
  },
};

// ...

What this means is that the standard environment for running our dapp (decentralized app) and its smart contracts needs to be on the localhost server (our computer), on the 8545 port (which matches the Ethereum Geth node that Embark is running).

dappConnection will determine how the web app should connect to the blockchain during its run. It prefers Web3 first and foremost – this is offered by MetaMask or an app like Status, and if the Web3 connection is unavailable (MetaMask isn’t installed or the app doesn’t provide Web3), it’ll go for a direct approach – first through websockets and if that fails through regular old HTTP. This section usually doesn’t need to be changed.

gas tells our environment how much gas to spend on deployments. In a local development environment, this is fine on auto, letting Embark decide.

Finally, there’s the most important part – the part which tells Embark which contracts to deploy. Without defining something here, none of our contracts will get deployed. Let’s assume we’ll build and deploy a contract called BitfallsToken. We need to change the contracts part:

contracts: {
  BitfallsToken: {}
}

Embark will now monitor the changes in our files and rebuild and recompile them as needed. In this case, Embark reports an error because the file we need doesn’t exist.

Embark error

Other configuration options can be seen in the official docs.

Let’s build the token now.

Dashboard

Embark Dashboard is a powerful tool which will be watching for changes in the files and recompiling them as needed, as seen above. For example, if we add the file contracts/BitfallsToken.sol or change the configuration in embark.json to make two JavaScript files merge into one, Embark will recognize this automatically and rebuild our project on a virtual blockchain spinning in the background.

If we add the file BitfallsToken.sol in the contracts folder with the following content:

pragma solidity ^0.4.25;

contract BitfallsToken {
    constructor() public {
    
    }
}

… you’ll notice that dashboard reacted to this and rebuilt our app, outputting the address on which the smart contract was deployed.

Deploy

Adding Other Software Packages

So we don’t develop a token from scratch, we’ll use existing templates from way better programmers. We’ll use OpenZeppelin’s library which we’ll then extend for our own purposes.

Do add OpenZeppelin’s contracts into our projects, we run the following command:

npm install openzeppelin-solidity@next

These smart contracts are now available in the node_modules folder and to use them we need to import them by adding an import statement at the top of the BitfallsToken.sol contract but below pragma:

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

Immediately after saving the file, Embark Dashboard will report a change and rebuild the files, sending the imported contracts to the blockchain.

Import deploy

The ERC20.sol contract we’re importing has its own imports: SafeMath and IERC20.sol of which the latter is just and interface – a description of which functions should exist in a smart contract, so it’s not deployed.

Example: the IERC20 interface defines that an ERC20 token must have a transfer function. If it does not, then it’s not a real ERC20 token. This helps exchanges and wallets easily implement new ERC20 tokens because they know which functions a token will have by default, allowing for only a minor code change to add a new token.

To make our own contract inherit functions from the ERC20 contract, we change the opening line of the contract’s body from contract BitfallsToken { to:

contract BitfallsToken is ERC20 {

is X means “inherits all functions from X, and can have other functions”.

After saving changes, Embark will rebuild the project automatically. The contracts which are already deployed will not be re-deployed unless changed.

Developing the Token

We now have a solid foundation for our token. Let’s personalize it by adding a symbol, name and number of decimals.

pragma solidity ^0.4.25;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract BitfallsToken is ERC20 {
    string public name = "Bitfalls Token";
    string public symbol = "MEH";
    uint256 public decimals = 18;
    
    constructor() public {
    
    }
}

After deployment, our token will be called “Bitfalls Token”, it’ll have the symbol “MEH”, and will have 18 decimals much like ether.

But this is useless to us – the token isn’t sent to anyone, but remains in the ether, just idling there. Let’s upgrade its constructor.

    constructor() public {
        _mint(msg.sender, 100 * 10**6 * 10**decimals);
    }

A constructor is a function which is automatically run only once for each contract during deployment and is usually used for initializing some state variables, settings, ownerships and permissions, ICO durations, etc. In this case we’re using it to call _mint which is an internal function present in the parent contract ERC20 and which lets us create a certain numbers of tokens in the balance of a specific user. Here, we’re adding all 100 million of our Bitfalls tokens to the sender of the message or, in other words, the address of the person who deployed this contract.

But… which address is that? Who is deploying it?

onDeploy

When running embark run, the private version of geth being run behind the scenes is the private node onto which our contracts are going to be deployed.

That node has its own Ethereum accounts from which it’s running commands, so msg.sender from the above code matches a random address generated by Geth. We don’t have access to that address, so the fact that we sent our tokens to that address isn’t very helpful. Actually, our tokens are useless because there’s no way to access them through “someone else’s” account.

We can get help from the onDeploy hook here. During a deployment process, Embark will fire off some trigger, or hooks. One is onDeploy which happens after every single deployed contract, and one is afterDeploy which happens after all contracts have been deployed. onDeploy is defined in the config/contracts.js file as an attribute of the contract we’re deploying.

Let’s define it for BitfallsToken in such a way that all the tokens are sent to an address which is under our control. You can get one easily with MetaMask. In my case, it’s 0x5666c33bb922F97B6721D3f932dfD9350C933a6F.

    contracts: {
      BitfallsToken: {
        "onDeploy": ["BitfallsToken.methods.transfer('0x5666c33bb922F97B6721D3f932dfD9350C933a6F', \"100000000000000000000000000\").send()"]
      },
    }

This literally means “During deployment of the Bitfalls Token, pick the method transfer and use it to send the address 0x566... 100 million tokens with 18 decimals”.

The escaped quotes \" are necessary around the big number because JavaScript gets confused by big numbers, so we need to turn them into strings.

Another problem remains: our address 0x5666c33bb922F97B6721D3f932dfD9350C933a6F doesn’t have any ether on this private blockchain, so it can’t use the token contract. In other words, it can’t send the tokens around. While we’re in local development mode, we can define the starting ether balance for accounts for which we have the private keys. We can easily get a private key from a MetaMask address by going to Details and then Export Private Key.

Note: take care not to share a private key you actually use on a wallet in regular life. Remember – the private key on a testnet or a local blockchain also unlocks the account on a mainnet!

After we’ve got the private key, the file config/contracts.js can be used to define how much ether we want on it.

// ...
  deployment: {
      host: "localhost", // Host of the blockchain node
      port: 8545, // Port of the blockchain node
      type: "rpc" // Type of connection (ws or rpc),
      // Accounts to use instead of the default account to populate your wallet
      ,accounts: [
         {
          privateKey: "72F515AD44...9C0",
          balance: "5 ether"  // You can set the balance of the account in the dev environment
         }

Finally, let’s re-run embark run (you can kill it with CTRL+C).

If we check the account balance now, we’ll see 5 ether.

5 ether
5 ether

Let’s add the “Bitfalls Token” by going to Add Token and entering our token’s address. The address is visible in the dashboard but also in chains.js.

Add token
Add token

After adding, our balance will be 5 ether and 100 million Bitfalls MEH tokens.

Token + ether
Token + ether

If we try to send tokens to another address, everything should work as expected.

Send token
Send token

Conclusion

As you can see, developing a token with Embark is very straightforward. The process of development is similar to those in other environments like Truffle, with the added advantage of Embark Dashboard and other helper tools which let us focus on development instead of tweaking the system.

In the next tutorial we’ll deal with adding custom functions into the token and a truly crucial part of smart contract development: testing.

LEAVE A REPLY

Please enter your comment!
Please enter your name here