Introduction

For this tutorial, we are going to use a very simple get and set contract. All this contract does is get and sets a value.

Note – This tutorial is built for Eris versions >= 0.11.1. For other versions of this tutorial please see below:

  • v0.11.0

Dependencies

Welcome! This tutorial assumes that you have a chain ready to deploy smart contracts to. Should you not have any idea what smart contracts are, please see our explainer here. If you do not have a chain ready to work on, please see our chain making tutorial.

Contracts Strategy

We are going to use a very simple get / set contract which sets a variable and gets that same variable. It is about the easiest interactive contract one can imagine and as such we will use that for showing how to work with the eris platform.

Overview of Tutorial

In general we are going to take two steps in order to get our contracts deployed to the blockchain:

  1. Make sure your application package has the proper information
  2. Deploy the contracts

Make A Contract for Idi

The first thing we’re going to do is to add a very simple contract.

cd ~/.eris/apps
mkdir idi
cd idi

Now you’ll make a file in this directory. Let’s assume that is called idi.sol and has the following contents

contract IdisContractsFTW {
  uint storedData;
  function set(uint x) {
    storedData = x;
  }
  function get() constant returns (uint retVal) {
    return storedData;
  }
}

What does this contract do? Well, it isn’t very interesting, we know. It merely gets and sets a value which is an unsigned integer type. Protip: Get the file with curl -X GET https://raw.githubusercontent.com/eris-ltd/coding/master/contracts/idi/idi.sol -o idi.sol rather than copy pasting.

Fixup your epm.yaml

Next we need to make an epm.yaml and make it look something like this:

jobs:
- name: setStorageBase
  job:
    set:
      val: 5
- name: deployStorageK
  job:
    deploy:
      contract: idi.sol
      wait: true
- name: setStorage
  job:
    call:
      destination: $deployStorageK
      data: set $setStorageBase
      wait: true
- name: queryStorage
  job:
    query-contract:
      destination: $deployStorageK
      data: get
- name: assertStorage
  job:
    assert:
      key: $queryStorage
      relation: eq
      val: $setStorageBase

Protip: Get the file with curl -X GET https://raw.githubusercontent.com/eris-ltd/coding/master/contracts/idi/epm.yaml -o epm.yaml

Now, what does this file mean? Well, this file is the manager file for how to deploy and test your smart contracts. eris:package_manager will read this file and perform a sequence of jobs with the various parameters supplied for the job type. It will perform these in the order they are built into the yaml file. So let’s go through them one by one and explain what each of these jobs are doing. For more on using various jobs please see the jobs specification.

Job 1: Set Job

The set job simply sets a variable. eris:package_manager includes a very naive key value store which can be used for pretty much anything.

Job 2: Deploy Job

This job will compile and deploy the idi.sol contract using Eris’ compiler service (or run your own locally). The job will wait for the deploy transaction to confirm before it will proceed.

Job 3: Call Job

This job will send a call to the contract. eris:package_manager will automagically utilize the abi’s produced during the compilation process and allow users to formulate contract calls using the very simple notation of functionName params. eris:package_manager also allows for variable expansion.

So what this job is doing is this. The job is pulling the value of the $setStorageBase job (eris:package_manager knows this because it resolved $ + jobName to the result of the setStorageBase job) and replacing that with the value, which is 5. Then it will send that 5 value to the set function of the contract which is at the destination that is the result of the deployStorageK job; in other words the result of Job 3. For more on variables in eris:package_manager, please see the variables specification.

Finally, it is waiting on the call to be sunk into a block before it will proceed.

Job 4: Query Contract Job

This job is going to send what are alternatively called simulated calls or just queries to an accessor function of a contract. In other words, these are read transactions. Generally the query-contract is married to an accessor function (such as get in the idi.sol contract). Usually accessor, or read only functions, in a solidity contracts are denoted as a constant function which means that any call sent to the contract will not update the state of the contract.

The value returned from a query-contract job then is usually paired with an assert.

Job 5: Assert Job

In order to know that things have deployed or gone through correctly, you need to be able to assert relations. eris:package_manager provides you with:

  • equality
  • non-equality
  • greater than or equals (for integers & unsigned integers values only)
  • greater than (for integers & unsigned integers values only)
  • less than or equals (for integers & unsigned integers values only)
  • less than (for integers & unsigned integers values only)

Relations can use either eq ne ge gt le lt syntax, or, in the alternative they can use == != >= > <= < syntax in the relation field. This is similar to Bash. To make this more explicit we have chosen in the above epm.yaml to use the eq syntax, but feel free to replace with == syntax if you want.

Both the key and the val (which in other testing frameworks are the given and expected in an assert function) use variable expansion to compare the result of what was supposed to be sent to the setStorageBase job (which should have been sent to and stored in the contracts’ storage) with what was received from the queryStorage job (which in turn called the get function of the contract).

Deploy (and Test) The Contract

See the chain making tutorial if you need to review the chain making process. This series of commands assumed you followed that tutorial and continued here after eris chains stop simplechain.

First, let’s get our chain turned back on.

eris chains ls

If it’s on, you’ll see:

CHAIN        ON     CONTAINER ID     DATA CONTAINER
simplechain  *      efeeb0dd63       d06301b3a5

Whereas if it has been stopped, the ON field will have - rather than *. The same logic applies to services.

If simplechain is not running, then turn it on with:

eris chains start simplechain

or create a new chain if simplechain no longer exists.

Now, we are ready to deploy this world changing contract. Make sure you are in the ~/.eris/apps/idi folder, or wherever you saved your epm.yaml. Note that this is a very common pattern in simple contract testing and development; namely to (1) deploy a contract; (2) send it some transactions (or calls); (3) query some results from the contract (or query-contracts); and (4) assert a result. As you get moving with contract development you will likely find yourself doing this a lot.

addr=$(cat $chain_dir/addresses.csv | grep simplechain_full_000 | cut -d ',' -f 1)
echo $addr

That will make sure we have available the address we would like to use to deploy the contracts. Now we’re ready. If the above does not output an address then check your $chain_dir variable and also check that the simplechain_full_000 variable exists in the addresses.csv.

eris pkgs do --chain simplechain --address $addr

You should be able to use any of the addresses you generated during the chainmaking tutorial since they all have the same permission levels on the chain (which, if you followed the simple tutorial are basically all public). If you are using this tutorial outside of the tutorial sequence then you can just give it the address that you’d like to use to sign transactions instead of the grep simplechain_full_000 bash expansion.

(For those that do not know what is happening in that bash line: cat is used to “print the file” and “pipe” it into the second command; grep is a finder tool which will find the line which has the right name we want to use; the cut says split the line at the , and give me the first field).

Note that eris:package_manager can override the account which is used in any single job and/or, eris:package_manager can set a default account job which will establish a default account within the yaml. We find setting the default account within the yaml to usually be counter-productive because others will not be able to easily use your yaml unless they have the same keys in their eris-keys (which we never recommend). For more on using accounts please see the jobs specification.

That’s it! Your contract is all ready to go. You should see the output in epm.json which will have the transaction hash of the transactions as well as the address of the deployed idi.sol contract.

Troubleshooting

If you get an error which looks something like this:

Performing action. This can sometimes take a wee while
Post http://chain:46657/status: dial tcp 172.17.0.3:46657: getsockopt: connection refused
Container eris_interactive_eris_service_idi_tmp_deploy_1 exited with status 1

That means that your chain is not started. Please start the chain and give the chain a second to reboot before rerunning the deploy command again.


If you get an error which looks something like this:

open /home/eris/.eris/keys/data/1040E6521541DAB4E7EE57F21226DD17CE9F0FB7/1040E6521541DAB4E7EE57F21226DD17CE9F0FB7: no such file or directory
Container 74a9dbf3d72a2f67e2280bc792e30c7b37fa57e3d04aeb348222f72448bdc84a exited with status 1

What is this telling us? Well, it is telling us that it doesn’t have the key in the keys container. So what you’ll want to do is to update with one of the keys you have generated during the prior tutorials.

To see what keys are currently on your key signing daemon do this:

eris keys ls

If you do not have any keys then please take the time to make some keys. After you find a key which you currently have, then add that as the address flag to the eris pkgs do command.


If you choose the wrong key then you’ll get an error which will probably look something like this:

Error deploying contract idi.sol: unknown account 03E3FAC131CC111D78B569CEC45FA42CE5DA8AD8
Container edbae127e1a31f1f85fbe14359362f7943028e57dc5eec4d91a71df706f5240f exited with status 1

This means that the account 03E3FAC131CC111D78B569CEC45FA42CE5DA8AD8 has not been registered in the genesis.json. The account which is not registered will be the same account you told epm to use via the signing server (eris-keys).

To “see” your genesis.json then do this:

eris chains cat simplechain genesis

You can also see your genesis.json at http://localhost:46657/genesis. Note: replace localhost with the output of docker-machine ip eris if on OSX or Windows. See our docker-machine tutorial for more information.


If the account you are trying to use has not been registered in the genesis.json (or, latterly, has not been given the appropriate permissions via permission transactions) and been given the appropriate permissions, then it will not be able to perform the actions it needs to in order to deploy and test the contract. The easiest thing to do at this point is to update your genesis.json.

Once you have the following sorted:

  1. The provided account parameter matches a key which is known to the signing daemon; and
  2. The provided account parameter matches an account in the genesis.json of a chain;

Then you’ll be ready to:

eris pkgs do --chain simplechain --address ADDR

Where ADDR in the above command is the address you want to use.


If you have an error which complains about how a container cannot be removed which looks something like this:

Error removing intermediate container 1f3a1d541241:
Driver btrfs failed to remove root filesystem
1f3a1d541241e757d48f34329508253e9ee139380b7b914a3b1104677eb0e8ee:
Failed to destroy btrfs snapshot: operation not permitted

Then rerun the pkgs do command with the --rm flag at the end, which will stop the containers from trying to be removed as part of the tear down sequence.


If you have an error complaining about not being able to reach the compiler service, like this:

failed to send HTTP request Post https://compilers.eris.industries:10114/compile: dial tcp: i/o timeout
Error compiling contracts
Post https://compilers.eris.industries:10114/compile: dial tcp: i/o timeout

Then that means one of the following:

  • You’re working offline, e.g. on the train, or
  • You’re behind a corporate firewall/proxy and can’t access the compiler URL.

To fix this, you can either go online, or download and run the compilers service locally by doing the following - you need to be online for this, though:

eris services start compilers

When you run this for the first time, it will download the compilers Docker image, and then start the service.

Once the service is running, you can deploy packages by adding the address of your compiler service to the command line parameters. Replace the IP address with your local IP address, depending on your OS. If you’re on Windows or Mac OS X, you will have to use the Docker-Machine VM’s IP address (192.168.99.100 by default):

eris pkgs do --chain simplechain --address $addr --compiler 192.168.99.100:9091

When you’re done with your work, you can stop the compilers service like the other eris services:

eris services stop compilers

End Troubleshooting

Since we have a deployed contract on a running chain, please do take a look at the available options for eris contracts with:

eris pkgs do -h

That’s it! :-)

Where to next?

Next you’ll want to interact with your contracts, so please see our contract interaction tutorial.

If you would like to learn more about how to program smart contracts, please see our smart contract tutorial series.

Edit this page