The potential of the Ethereum platform, what most would call a cryptocurrency, is astonishing. However, developing a decentralised app (Dapp) that runs on the Ethereum platform sucks.
Author’s note: Of course it isn’t a cryptocurrency at all, but rather a protocol that allows the creation of decentralised applications (Dapps) powered by ETH, which is a cryptocurrency.
I originally started writing this blog post as a guide to building a Dapp. “How to build your first Dapp” was a working title. I budgeted three days to put together a really simple example project — an app to store short strings of text describing an “idea” to prove you had it first.
As you can imagine, it did not go to plan.
Why does it suck?
The state of the Ethereum platform is unusual. We currently have a blockchain network handling billions of dollars of transactions built on what is essentially a working proof of concept. This is due to the fast growth and adoption of the platform, fuelled by imaginative developers, eager cryptocurrency enthusiasts, and completely irrational “retail investors” hungry to make a quick buck and frustrated by the costs and inherent unfairness of existing investment opportunities.
The result is an ecosystem of unfinished projects, developed by the inexperienced, marketed to the uneducated, and built on quickly moving sands of a protocol in development.
The protocol sucks. The documentation sucks. The APIs suck. The users suck. The developers suck. The communities suck.
In most other circumstances, this would be a recipe for disaster. But Ethereum, even in its current state, keeps everybody happy.
- Developers have an opportunity to get into a developing market before it becomes saturated. There is no Facebook of Ethereum yet. There is no Amazon or Google. There may never be, but for now, it’s open country and that’s exciting.
- Crypto enthusiasts have a real competitor to Bitcoin, both in technology and market cap.
- Retail investors finally get an opportunity to make significant returns without a massive up-front cost. Sure it’s risky as all hell, but before now, if I had €1000 (or even less) to invest, I was stuck with the interest rates of a savings account.
How does it suck?
Here’s where things get technical. Most of this will not be relevant to non-technical users. So feel free to skip to the conclusion and give me a few claps.
The protocol is unstable.
The Ethereum protocol is the foundation of the entire ecosystem. The concepts are good, but the implementation is lacking. I could list any number of specific issues with the protocol but that is beside the point. It is great that the protocol is being actively developed and improved but without a stable protocol release, tooling, APIs, languages, Dapps and everything will suffer.
The rest of this section will be mainly about things that suck because the protocol is unstable.
Solidity is, of course, only one language built to compile into Ethereum machine code. But, it is the most popular (currently) and therefore enjoys the best tooling, frameworks and community. In my (limited) experience, it’s the only useable option at the moment.
However, the language has some very strange quirks. The most obvious and bizarre one that I have encountered so far is the reverse order of array definition syntax. In most languages, an array of 5 ‘things’ looks like this:
This produces an array that might look like:
[thing1, thing2, thing3, thing4, thing5]
A 2-dimensional array of things is similar. For example, an array of 5 arrays of 3 things each would be defined like:
[ [1,2,3], [4,5,6], [7,8,9], [10, 11, 12], [13, 14, 15] ]
In solidity, an array of 5 arrays of 3 things each is actually defined like:
Even worse, is that this isn’t uniform throughout Solidity! Imagine you wanted to retrieve the number 8 from the example 5x3 array above. Now that we know the array definition syntax is reverse, we might try something like so:
Or in English, ‘the element in position 1 of the element in position 2’.
But no. In this context, Solidity decides to use the more standard syntax:
Which gets the element in position 2, and then gets the element in position 1 of that.
Now throw in the cryptic compiler errors like
ParserError: Expected primary expression. and the inability of functions to return strings (WHAT? Yeah…) meaning you end up spending far more time figuring out how to solve trivial little things (LIKE RETURNING A STRING FROM A FUNCTION!!) rather than actually building something useful.
The tooling is broken
I feel conflicted here. Firstly, the tools you need to build a Dapp are actually surprisingly good considering the state of the ecosystem at large. Truffle provides awesome tools to get up and running really easily — scaffolding a project is a single command, testing is super easy and seamless with build in test networks. Even running them locally is a breeze once you get your head around it. MetaMask connects you to whatever network you specify and provides an API.
But things start to fall apart very quickly.
If you run your app locally, you need to run a test network like truffle-develop or Ganache. Sadly, Ganache tends to crash every now and then which isn’t a problem in itself but it results in your local network starting from scratch — losing all state.
This isn’t too bad until we try making a transaction with our Dapp in the browser again… this requires MetaMask to connect to the Ganache network, but MetaMask caches some information and doesn’t know Ganache has crashes. This leaves the two systems out of sync and the transaction fails with a nice, cryptic warning about nonces.
This issue has been posted on Github since August 2017 and the developers of MetaMask are aware of it and are working on a solution. But for now, there are five or six “solutions” posted in various places that have not worked for me. Nothing short of completely reinstalling MetaMask will work — which might be required every couple of hours. Maybe that warning was correct...I am a nonce.
The web3 API
One example is the
web3.fromAscii() function. As I mentioned before, solidity doesn’t handle strings very well (ARGHHH) so one solution might be to store a fixed length array of bytes and encode/decode on the client. One might expect the web3.fromAscii() (and accompanying toAscii()) function to help with this…but it turns out it’s more trouble than it’s worth.
The documentation says:
Converts any ASCII string to a HEX string.
String- An ASCII string to be converted to HEX.
Number- (optional) The number of bytes the returned HEX string should have.
Number parameter actually doesn’t do anything. So what? you ask. Well when you are trying to store a string in a fixed sized byte array — it’s super important that the size of the bytes match the size of the array. Otherwise you end up with weird edge cases where strings half over-write each other and get garbled.
In the end, I wrote my own toAscii and fromAscii functions but not until I’d wasted an entire evening puzzled and frustrated with missing bytes and strange unicode characters appearing out of nowhere.
Most of my frustration could be put down to two things:
- Unfamiliarity with a new set of technologies.
- An immature ecosystem of breaking changes.
My last post dissected Crypto Kitties and left me eager to build something cool. I have lost hope of building anything in the ballpark of Crypto Kitties, but I have gained and enormous respect for the Crypto Kitties devs.
Personally, I think the Ethereum platform is in its infancy. With Proof-of-Stake and side-chain improvements on the way, things are only going to get better, faster and more useful. However, it is imperative that the Ethereum tech ecosystem stabilizes sooner rather than later. Only the boldest developers will attempt to build anything worthwhile in this ecosystem. Without Dapp developers, there are no Dapps, and without Dapps, Ethereum is nothing special.
I’ve complained a lot in this post, but I should mention that the only reason I have anything to complain about is that there are incredible developers and engineers out there building this brave new world. Keep it up!
If you’re an ETH “whale” share the love: 0xE3649aC33Bb4A0d99cD285661782fDBa8c701E2b