OpenZeppelin Blog

Getting started with ZepKit - OpenZeppelin blog

Written by OpenZeppelin | February 13, 2019

 

by Dennison Bertram

The ZeppelinOS ZepKit is designed to be a one-stop shop for getting started with developing secure, upgradable smart contracts and EVM packages. It includes ZeppelinOS, two sample projects, and a complete React application to get your Ethereum smart contract–powered application running as quickly as possible. To get started with ZepKit, we’re going to install a few pieces of software: ZeppelinOS, Ganache, and Truffle.

npm install -g truffle@5.0.2 && npm install -g ganache-cli@6.3.0
npm install -g zos@2.1.2

Additionally, if you haven’t installed a browser-based web3 wallet such as Metamask or Nifty Wallet, now is the time to do so as you will need one later to interact with the web application. Feel free to use either wallet; they will both work fine.

Install ZepKit

To install ZepKit:

truffle unbox zeppelinos/zepkit

Open a new terminal window, navigate to the client folder, and start the React server by typing the following:

npm run start

This will open a new browser window at http://localhost:3000, which should look like this:

Intro screen when the server is running

There are two demo examples included in ZepKit: Counter Example and Using EVM packages. To get started, let’s check out the Counter Example.

ZepKit Counter Example

Now let’s get started! Note the message which says:

“Your contracts are not deployed in this network.”

First things first: check your MetaMask or Nifty Wallet to be sure it’s unlocked (you might receive a popup requesting access, which you should approve), and check the network you’re connected to.

The ZepKit React application receives a connection to the Ethereum network through Metamask or Nifty Wallet, and for the moment, you haven’t deployed any contracts. So naturally, none are detected. Let’s get the contracts deployed on the network!

Development Network

In our first step, we installed Ganache-cli, which we’ll use as our development network.

If you already have experience using Ganache-cli, feel free to use a setup that you’re already comfortable with. For beginners, I would recommend reading my EVM package deployment with ZeppelinOS — Part I with a focus on the part where I go over deployment to a development network. In this tutorial, the 12-word mnemonic that we’ll use with Ganache-cli, we’ll also use as the mnemonic for our MetaMask or Nifty Wallet browser extension. The MetaMask setup instructions are the same as those for Nifty Wallet.

Start Ganache-cli in a new terminal window with the mnemonic you’ll later use in MetaMask or Nifty Wallet, like so:

ganache-cli --secure --u 0 --u 9 --mnemonic “your twelve word mnemonic here” 

The -u means we’ll unlock the first account and the 10th account (they are zero indexed). The first account is the account we’ll use to interact with the contract while we’re developing, and we’ll reserve the 10th account for interacting with any proxies if necessary.

Update:  In the very near future, when ZeppelinOS 2.2.0 is released, there will be a new implementation which takes care of interacting directly with proxies, so you won’t need to unlock your 10th address. Refer to the documentation for the latest version.

With Ganache-cli still running in a different terminal window, return to your original terminal window at the top level of your project.

The first step is to initialize ZeppelinOS:

zos init zepkit

Now we want to create a session:

zos session --network development --from <<your 10th unlocked ganache address>>

Note: This may change for ZeppelinOS 2.2.0. Refer to the documentation for most recent information.

So, for example, in my case it would look like this:

zos session --network development --from 0x1df62f291b2e969fb0849d99d9ce41d2f147006e

If you look at the `contracts` folder, you will see that there are two demo contracts: `Counter.sol` and `Wallet.sol`. We’re going to add the `Counter.sol` contract to our ZeppelinOS project. In your terminal, from you your top-level project folder type:

zos add Counter

(Note: We do not need the file extension .sol for this command.)

Now let’s push our project to our development blockchain.

zos push

Before we create an instance of our Counter contract, let’s take a look at the source code.

pragma solidity ^ 0.5 .0;
// import "openzeppelin-eth/contracts/ownership/Ownable.sol";
import "zos-lib/contracts/Initializable.sol";
contract Counter is Initializable {
  //it keeps a count to demonstrate stage changes
  uint private count;
  address private _owner;

  function initialize(uint num) initializer public {  
    _owner = msg.sender;  
    count = num;
  }

  function owner() public view returns(address) {  
    return _owner;
  }
  // getter
  function getCounter() public view returns(uint) {  
    return count;
  }
  //and it can add to a count
  function increaseCounter(uint256 amount) public {  
    count = count + amount;
  }
  //We'll upgrade the contract with this function after deploying it
  //function decreaseCounter(uint256 amount) public returns (bool) {
  // require(count > amount, "Cannot be lower than 0");
  // count = count - amount;
  // return true;
  }
}

Our initialize()function here takes the place of a constructor function, and we’ll need to call it when we create the contract with the command zos create Counter --init followed by initialize and the arguments that the initialize() function receives. For more in-depth information about deployment with ZeppelinOS, please have a look at one of our other tutorials and the official documentation.

Let’s create a Counter instance from our project on our development blockchain.

zos create Counter--init initialize--args 2
Using session with network development, sender address 0x7a77716facf9df1efa78d389a122d8a0b754193c Creating proxy to logic contract 0xd8502e37789adbc15f61b8979315cdb1f493d31d and initializing by calling initialize with: —num(uint256): “2” Instance created at 0x281c953917ebab92f5fd5579f243e2853e32908c 0x281c953917ebab92f5fd5579f243e2853e32908c Updated zos.dev - 1549467365638. json

Your addresses and the zos.dev-<<network-ID-here>>.json file will be unique to your project and setup.

The “network-ID-here” will be a number that represents the network ID of your development network. This will be generated for you, but if you’re curious, you can see some public network IDs.

Checking to be sure that MetaMask or Nifty Wallet is connected to your development blockchain, switch to the terminal window where your React server is running. Kill the process manually and restart it with the following:

npm run start

When it restarts, switch to your browser tab that is pointed to localhost:3000. Be sure that MetaMask or Nifty Wallet is connected to your Ganache blockchain, and click Refresh (if it hasn’t refreshed itself). The app should detect your contracts on the network, like so:

When it restarts, switch to your browser tab that is pointed to localhost:3000. Be sure that MetaMask or Nifty Wallet is connected to your Ganache blockchain, and click Refresh (if it hasn’t refreshed itself). The app should detect your contracts on the network, like so:

That was easy!

Both “Your Web3 Info” and “Your Counter Contract Instance” are React components that  can be found inside the client directory under /source/components. Feel free to poke around to see how they work!

Next, let’s test out our Counter contract by clicking on Increase Counter by 1 button. A MetaMask or Nifty Wallet popup will come up for each click to create a transaction to the blockchain. You’ll see the counter value update once the transaction confirms. The Decrease button is disabled for now, and perhaps you noticed that the `decreaseCounter` function in our Counter.sol was commented out. So let’s upgrade our contract to enable it!

Time to Upgrade

To upgrade your Counter.sol contract, uncomment lines 32–36 to enable the decreaseCounter function so it looks like this:

//We’ll upgrade the contract with this function after deploying it
//Function to decrease the counter
function decreaseCounter(uint256 amount) public returns(bool) {
  require(count > amount, “Cannot be lower than 0”);
  count = count— amount;
  return true;
}

Now that we have a new function enabled in our contract, we’ll use ZeppelinOS to upgrade it.

  • If you’re using ZeppelinOS version 2.1, return to your terminal window command line and type the following:
 truffle compile --all

zos push

This will refresh all the compiled contracts and push the changes to our blockchain.

  • If you’re using ZeppelinOS version 2.2, you can omit the truffle compile --all command and just type the following:
zos push

Now that our project changes are pushed to the blockchain, we need to update our Counter instance.

zos update Counter

This will update our Counter contract to the latest version. Return to your browser window to refresh it, and you’ll see that Decrease Counter by 1 is now dark blue. When you click it, MetaMask or Nifty Wallet will pop up to create your transaction. It works!

Next Step:  EVM packages — Upgrading!

Now that you have the Counter example under your belt, let’s move on to linking EVM packages.

ZepKit provides the perfect boilerplate environment to get started creating and testing EVM packages. For an in-depth understanding of how to create, deploy, and link EVM packages, read EVM package deployment with ZeppelinOS. You can also find out what kind of Ethereum smart contracts make for good EVM packages.

We’re going to be building on the ERC20 standard, and we’re going to use the OpenZeppelin-eth ERC20 EVM package implementation. ZeppelinOS makes the process quick and easy. All we need to do is link the package and ZeppelinOS will take care of the rest to make sure it’s available in our project.

zos link openzeppelin-eth

This command downloads openzeppelin-eth from NPM, and includes the contract code in our `node_modules` folder. Now we have the source code available directly in our project. If you look inside your zos.json file at the project top level, you’ll see that openzeppelin-eth has also been added as a listed dependency.

The OpenZeppelin-Eth EVM package  is a version of the popular OpenZeppelin-Solitidy secure audited smart contracts, adapted to work with EVM packages and ZeppelinOS. The openzeppelin-eth EVM package has already been deployed by Zeppelin on the mainnet and all the major test-nets, so they’re ready for use if you want to link to them on those networks. For our project, however, we’re using a private development blockchain, and those contracts are not yet deployed. We’ll need to do that ourselves.

First, let’s add our Wallet.sol contract, which is found in our top-level contracts folder.

zos add Wallet

If you look inside the zos.json file again, you’ll see that “Wallet” has been added to your contract object.

Now that we’ve added Wallet.sol to our project, before we can create an instance of it, we need to push it to our local blockchain. But first, let’s look at our Wallet.sol code.

pragma solidity ^ 0.5 .0;
import "openzeppelin-eth/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-eth/contracts/ownership/Ownable.sol";
import "zos-lib/contracts/Initializable.sol";
contract Wallet is Ownable {
  function transferERC20(IERC20 token, address to, uint256 amount) public onlyOwner returns(bool) {  
    require(token.transfer(to, amount));
  }
}

So simple! Believe it or not, in only 10 lines of code, you can deploy an audited and secure ERC20 token!

If you were to type zos push right now, as we did previously with our Counter example, you’d get an error saying this:

Failed to link dependency openzeppelin-eth@^2.1.3 with error: Could not find a zos file for network 'dev-<<network-id>>' for 'openzeppelin-eth'

This is because although we have linked the openzeppelin-eth contracts to our project as dependencies, we haven’t actually deployed them yet to our development network. To do this, we add the flag --deploy-dependencies.

zos push --deploy-dependencies

Now that we’ve pushed our code to the blockchain, let’s create an instance of our wallet.

zos create Wallet --init --args 0x0A342460053e4621F692B14DF2E966788350642B

This will create an instance of the Wallet contract on the blockchain. Switch over to your browser window and refresh the page: now you’ll see your Wallet contract!

Now it’s time to explore on your own. Linking to EVM packages documentation offers a great example of how you can now actually create an ERC20 token with only one line of code. Want a hint? Type this into your terminal at the top level of your project:

zos create openzeppelin-eth/StandaloneERC20 --init --args 'MyToken,MYT,8,10000000000,0x0A342460053e4621F692B14DF2E966788350642B,[],[]'

Bingo! You’ve just created a new ERC20 token right on your development network!

We’re really excited to see what you build on ZeppelinOS using the ZepKit. We think it’s going to be a great tool to jumpstart development and supercharge hackathon projects. We’ll be creating more documentation and examples, so we would really appreciate your feedback. Tweet me on Twitter.

Thanks to Jota for reviewing!