Your first EOS dApp — The Contract

source

In our previous article we setup our standalone EOS chain and our wallet and account. In this article we will code the contract that we will use to run our school admission lottery. We will learn core EOS concepts like

  • How do I create my EOS smart contract
  • What is web assembly and what is it used for in EOS
  • How do I deploy and interact with my EOS contracts

Setup

I would suggest getting an IDE like Visual Studio Code, but you can really use any editor. Let’s go ahead and create the following file and project directory.

mkdir lottery && cd lottery
mkdir contracts && cd contracts
mkdir lottery && cd lottery

Code

Create a Lottery.cpp file in the path lottery/contracts/lottery/Lottery.cpp

Compile

EOS is making a big bet on Web Assembly and has chosen it as the runtime environment for their contracts to be executed in.

Web Assembly is an emerging industry standard backed by Microsoft, Google, and Apple. The goal of this standard is to make it possible to run untrusted high-performance code in your browser. Web Assembly is a game changer, it will enable high performance web applications such as video and image editing and games. — Dan Larimer

Here we generate the web assembly(.wast) from our .cpp file through the use of our eosiocpp that is available to us from our install in the previous article. Note you will need to adjust your path if you are not in the lottery/contracts/lottery folder.

eosiocpp -o Lottery.wast Lottery.cpp

The ABI is common to most blockchain projects and is essentially an interface that describes the actions and attributes of the smart contract that are available to the caller. Note the //@abi syntax in the Lottery.cpp file that tells our eosiocpp compiler what members are to be exposed and in what way.

eosiocpp -g Lottery.abi Lottery.cpp

Deploy

You will need to start your EOS chain if it is not already started. You may need to unlock your wallet as well.

Start Chain

You will need to run the command below from the directory that you installed and built EOS in.

Note that we are running dawn-v4.1.0 and we have an additional parameter that allows us to see our print() methods and the history plugin has changed names to history_api_plugin

./build/programs/nodeos/nodeos -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_api_plugin --contracts-console

Unlock Wallet

cleos wallet unlock -n lottery

Enter the password that you saved in the previous article for the lottery wallet.

Your lottery.code account should still exist from your work in the previous article, but if you have upgraded chains and lost data, you can run this to recreate it.

cleos create account eosio lottery.code <owner public key> <active public key>

Deploy Contract

Now that we have our .wast and .abi file with a running chain and unlocked wallet, we can deploy this contract! Note that this command is run from the lottery root project folder.

cleos set contract lottery.code ./contracts/lottery ./contracts/lottery/Lottery.wast ./contracts/lottery/Lottery.abi

Test Accounts

We need to create two more accounts to run through this contract.

  • admin — This account is for the school admin running the lottery
  • parent — This account is for a parent to enter their student into the lottery

Please run through the account creation process described here or see the summary of commands below.

For each account:

// Generate owner public/private keys
cleos create key
// Import owner private key into wallet
cleos wallet import <owner private key hash> -n lottery
// Generate active public/private keys
cleos create key
// Import active private key into wallet
cleos wallet import <active private key hash> -n lottery
// Create account
cleos create account eosio <account name> <owner public key> <active public key>

Once you have the admin and parent accounts created, we will be able to run through the test scripts later in the article.

Interact with Contract

Now that the contract is deployed to the chain, we can begin to interact with it. We have three user facing functions:

  • Add Grade — We need to add the grade level and available openings(This should only be accessible to the supervisor account)
  • Remove Grade — We need to remove the grade level(This should only be accessible to the supervisor account)
  • Get Grade — Get the grade level and available openings(This should be accessible to all accounts)
  • Add Student — We need a way for parents to be able to enter their child’s information to enter them in the lottery. This should be available to all accounts but we will create a parent account for this purpose. At this time the parent is restricted to entering a single student.
  • Remove Student — The parent account that entered the student should be able to remove the student from the lottery.
  • Get Student — The parent account that entered the student or the supervisor should be able to get the student to check his/her lottery status
  • Run Lottery — The supervisor account should be able to run the lottery for all grades

Test Script

In the interest of efficiency, the test script below may be run to illustrate the requirements above.

Disclaimer: I have not been able to explore permissions on the contracts other than requiring the caller to be an authorized account and owning their own inserted data. If anyone can point me in the direction of locking down certain actions of a smart contract that would be helpful. The only way I could think to do it was to maintain my own table of permissions?

The tests above are not ideal in their current form, but actually none of this is ideal in a developer environment. This stack is light years behind a truffle dev environment, but I will be exploring using Tokenika’s product, EOS Factory in the next article to address a more real world developer flow. That being said, there is nothing wrong with doing something the hard way and getting a basic understanding of the EOS CLI tools.


Troubleshooting

Running the EOS chain locally is quite challenging and there will be a situation where it will be in an invalid state. Every morning I have to reset my chain as transactions have expired and it’s unusable.

rm -rf "~/Library/Application Support/eosio/nodeos/data"
<eos dir>/build/programs/nodeos/nodeos -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_api_plugin --contracts-console