Ethereum-Event-Explorer for Smart Contracts based on Web3.js and Node.js

BY MARKUS SPRUNCK

Motivation

Ethereum-Event-Scan is a lightweight Ethereum Event Explorer for SmartContracts.

A helpful tool, when you develop smart contracts and your source code is not yet submitted to etherscan.io. Also in the case you work with a private Ethereum blockchain, you will need a tool to monitor what happens in you contract.

The following article describes the key ideas, design behind the implementation and usage as out of the box docker image. You may find the complete source code on GitHub.

Figure 1: Main Screen of Ethereum-Event-Scan

Introduction

In principle there are two approaches to find out what happens in your deployed SmartContract.

The first way is just to monitor all transactions of your contract and the second is to monitor events emitted by your SmartContract.

Monitor Transactions

It is easy to get all incoming transactions of your contract - but you have to decode the transaction input based on the ABI description.

Decoding is not rocket science, however you see just the input parameters of the method calls. With this approach you never see what happens in the SmartContract. In most cases you are also interested in the internal states of your contract , so a kind of logging would be needed.

Monitor Events

When your SmartContract emits events you can also add information of the transaction result, e.g. updated balance or statistics. This internal state can give you the needed information for monitoring.

Solidity Event Basics

In Solidity an event will be emitted by emit keyword, followed by the name of the event and the arguments in parentheses. The invocation can be detected from the JavaScript API (web3).

Let's have a look at an example contract

When the method bee() is called, the internal attribute _count will be incremented. This counter represents an internal state of the contract.

The emitted Bee events can output this internal state information. You may use the keyword indexed to filter later by this parameter.

How are events stored in the blockchain?

The needed storage for all events in the blockchain would be very expensive. How can we get events without actually storing them in the blockchain?

When a smart contract emits events - like in the bee() method - just the contract address is stored in the transactions receipt as logsBloom. This data structure has a size of 2048 bytes and is part of the block hash calculation. So, it can't be changed after the block has been mined.

How can we find events data?

The addresses of events emitting contracts are as well as indexed fields added to the bloom filter. A bloom filter of the given size can store about 200 contract addresses with less than 2% expected false positive results. Bloom filters have no false negative results.

When you query the log entries for a given contract address, it can be scanned in a very fast way over all the block headers, checking the bloom filter to find out this block may contain the entries.

In this case all transactions from that block will be re-executed and this execution recreates the expected logged events.

How to use events in your contract?

Find more information about events and logs in the Solidity Documentation which provides a detailed description of how to use events.

Let's talk about money

The use of Ethereum events will cost some extra GAS, but in most of the cases it is a good investment.

By the way - the GAS price of event Logs is much more cheaper than contract storage. In the case the SmartContract doesn't need the stored data for processing - it's may be an alternative to store data in logs.

Find Code on GitHub

Fetch the project sources from GitHub

https://github.com/MarkusSprunck/ethereum-event-scan

You should see a project structure like this:

Dependent Libraries

The most important library is web3, the other dependencies are more or less needed for the user interface.

Zlib is used to compress the url parameter ABI - this happens because very long ABI arrays would exceed the practical maximum length for bookmarks.

Development Environment

The project has been developed and tested with following configuration:

  • macOS 10.14.6
  • IDEA IntelliJ (Ultimate Edition)
  • Package Manager Brew (see https://brew.sh)
  • Docker Desktop (Community Edition) v2.1.0.2
  • Parity Node v2.5.7
  • Ganache v2.0.1
  • Web3.js v1.2.1
  • Node.js v6.10.2

Resolve Dependencies with Browserify

Unfortunately, web3.js project does not provide a library which can be loaded directly in the browser. You have to use the node.js style of dependencies (require).

With Browserify you can write code that uses require in the same way that you would use it in Node.

The following command line:

$ browserify ./src/main.js -o ./dist/bundle.js

Resolves all dependencies in main.js and create the output bundle.js which can run in a browser without node.js.

Connect to Kovan via Blockchain Gateway

Use Infura.io to connect to a Blockchain is the fastest way to get events from a deployed contract. You will need an account and project id.

The following three steps are needed:

  • Create an Infura.io Project
  • Update the Start Script
  • Enter ABI and Contract Address

Create an Infura.io Project

Open Infura.io page and sign up for an account. On your dashboard, you can create a new project.

Usually, you change the endpoint to Kovan and copy the endpoint URL for connecting to blockchain.

But, to get events from infura you must use in the Ethereum-Event-Explorer the web socket connection provider (with a slightly different URL). The correct pattern for web services is:

wss://kovan.infura.io/ws/v3/{your-infura-project-id}  

Your personal API key to use Infura should be secret. So, don’t give it away to anyone else.

Update the Start Script

Now you can replace {change-me} with your created Infura project and start the Ethereum-Event-Scan application with the prepared start script

$ ./start-ethereum-event-scan-infura.sh

Enter ABI and Contract Address

Enter the ABI array and contract address can be done directly in the user interface or you can click on Import link. In the case you stored the ABI array in a file with the file name of the contract address.

Connect to Kovan via Local Parity Node

The installation of a parity node on your machine is simple. Three steps are needed:

  • Install Parity Node
  • Start and Synchronise Parity Node
  • Start Ethereum-Event-Scan

Install Parity Node

For MacOS open terminal and enter the following two commands:

$ brew tap paritytech/paritytech
$ brew install parity

After parity has been installed you can start the partiy node and fetch the blockchain from Kovan network.

Start and Synchronise Parity Node

The following start script (see start-parity.sh) enables just the needed api for the Ethereum event scan for web socket connections:

#!/usr/bin/env bash  # start local node parity --chain kovan --ws-apis="web3,eth,net"       \                      --ws-origins="localhost:55226"         \                      --no-jsonrpc                                      \                      --no-ipc

The synchronisation may need a day. In the case the synchronisation got stuck, just restart.

You should see an output of the Parity Node after complete sync and restart should look like this:

Please, be aware that the Public node URL has been slightly changed. So, don't try to connect to this node.

In the logging of this parity node you see also the open connection of the configured web service interface - here 127.0.0.1 with port 8546.

Start Ethereum-Event-Scan

Now you can start the Ethereum-Event-Scan application with the prepared start script

$ ./start-ethereum-event-scan-local.sh
#!/usr/bin/env bash  # ensure that all libs have been installed npm install --quiet  # resolve all dependencies of node libs to run in the browser browserify ./src/main.js -o ./dist/bundle.js  # start node server node ./src/server.js ws://127.0.0.1:8546 localhost