How to solve the problems with addresses for smart contracts?
Libellum is our home-grown product, designed to take advantage of smart contracts on an Ethereum blockchain. The decentralized nature of this network allows us to provide a service for manufacturers that want to certificate their valuable products. During the development phase, we came across some inconveniences, though. Read more about Libellum here.
Overview of the architecture
Our goal was to support both payments by Ethereum wallets and by credit cards, for less tech-savvy clients. In case a client decides to pay by credit card, we have to use our wallet and pay on his behalf.
To achieve this, we decided to build the backend in Ruby and use two decentralized front-end clients (dApps) in React. We also took advantage of web3, the most established library that allows for connecting to the Ethereum node. Since it’s written in JavaScript, we decided to implement AWS Lambda functions in Node.js and invoke them via our backend.
Problem with addresses
The problem occurred once we wanted to keep addresses in all environments (development, test, staging, production) in sync. Each deployment of a new version of any contract required us to set the new address in both FE clients and AWS Lambda functions, as well as requiring us to inform all developers that they should update versions on local machines, too. This turned out to be very annoying and time-consuming in the long term. We decided to spend some time addressing the issue.
Ethereum Name Service
The first solution that came to our minds was to use a public ENS (Ethereum Name Service), which is a “DNS” for smart contracts. Analogically to DNS, this service points unique domain names to the complex, long and difficult to remember addresses. Everything is stored on the same blockchain where our smart contracts live. Moreover, you can change the address at any time, so we don’t have to do it in the many configs of our applications, but only in the ENS. Excellent!
However, domain registration in ENS takes some time and you need to lock your Ether in order to own it, or register a .test domain which expires after 28 days. Also, your domain doesn’t point to your address directly; it points to the resolver contract that you have to deploy (for managing all subdomains on your own). In the rapid development phase, we would like to bypass this process and have some kind of tagging and versioning.
Our resolver
We decided to prepare a slim version of the resolver contract and a set of helpers that simplify managing addresses to the bare minimum, without having to rely on ENS. We also came up with the possibility of tagging addresses, such as v1, v2, test, latest, default, production, etc.
We also prepared a script that you can load in a geth console and use convenient functions that allow you to configure the names pointing to addresses. These helpers can be imported in your JS code as well. You can find the open source code, full documentation, and examples here.
The contract is compatible with official ENS standards so, eventually, it will be possible to register your real domain and point to this resolver.
An example of usage
Let’s assume we want to write a simple web server in Express.js that will have two end-points for setting and getting addresses.
In our example, we use Ganache, which allows us to deploy smart contracts and test our network in the local environment. Installation on a Mac comes down to downloading the app and opening it – we don’t need to configure anything.
Once we have Ganache running, we can deploy our resolver contract. First, we have to clone the repository.
Next, we have to install all node dependencies.
One of our dependencies is a truffle, development framework, that will help us to easily deploy our contracts. We configured truffle to support a Ganache network for you (in truffle.js file), so we can deploy it with one command:
We should see the address of our contract:
We will need this address later.
Now, we can initiate our Express application. Let’s create a directory for it and init a new node project:
Then we can install Express with body-parser and Web3:
We can also download a utilities script from our repo:
After all this, we can create our server in the server.js file.
First, we have to import express and Web3 libraries.
Secondly, we will need our utils module:
Thirdly, we will create an instance of Web3:
Port 7545 is the default port that Ganache use, you can change it in settings if you need.
Next, we will create an instance of utils passing a Web3 instance as a dependency:
Now, we can build two endpoints:
The whole listing is available here:
Let’s save the file and run the server:
We have two endpoints:
First, we can check that the address for `libellum.eth` domain has the `default` tag:
https://tooploox.com:3000/addresses/libellum.eth/default
We can see that the address is 0x0000000000000000000000000000000000000000. It means that it’s basically undefined.
We can simply set this via a POST request:
Now you can refresh the browser – et voila! The address is changed.
Hopefully, this example gives you the idea on how to use the resolver in your application.
Summary
As we follow the KISS (Keep it simple, stupid!) principle, we prefer not to over complicate simple things and save as much time as it’s possible. We hope the Tagged Public Resolver will save your time as well. Let us know what you think about it and how you deal with these issues.