A couple of months ago I decided to build my first game. I had two main goals. First and foremost, to brush off my solidity coding skills and second to build something fun that would teach people the skills and give them the tools to interact with decentralized applications. After having launched the game some days ago, I thought it would be interesting to share some of the key lessons I took away from developing the game.
What is coinclicker.io?
Coinclicker.io is an idle game loosely based on cookieclicker, a tremendously fun free browser game that has been around for a while. The enticing part of this game is the explorational element. While it seems quite straightforward when you start, more and more options will unlock as you progress through the game which makes it more interesting. There is, however, no clear goal to the game. In my version of the game, this is a bit different. Throughout the game there are many things you can unlock and upgrade, however there is a clear end goal. The goal is to claim an end-game NFT which you can only get by playing the game. While you are playing there are some ways to influence the progress other players are making. Moreover you can actually see their progress. Finally it is important to mention that the game is, aside from transaction costs, free to play. In fact it is aimed to teach people about core concepts like gas and gasprice.
Aside from the game itself and the meme driven funny character of it, it hopes to teach some aspects of decentralized apps. Gas price, blocks and tokens are an essential part of the game. In fact, by playing, players gain governance tokens with which they can influence the future of the game.
So what did I learn from creating my first released decentralized application.
Choose the right chain
Having left the crypto landscape during the downturn in 2018 some things have changed, while ethereum is still the leading chain in the crypto space, some alternatives have emerged. There are quite a few new chains to choose from. As coinclicker relies on making quite a few transactions, transaction cost and ease of access was leading in making the decision. I ended up going with Fantom as it has high speed and low transaction cost, while still supporting the EVM (ethereum virtual machine).
Test, test, test, test
After working on this app for about three months. I learned one thing above all else. In blockchain testing and to some extent test driven development is absolutely essential. After completing ethernaut I realized many things can go wrong when developing an dapp. Be sure to write many test cases in order to make sure there are no obvious vulnerabilities and there is no regression as you create the game.
Contract size limitations
One of the more challenging issues I encountered was the amount of code I tried to squeeze into the contracts. I ended up putting most of the code in separate libraries but I am unsure if this, from the perspective of upgradeability, was the best choice in the end. One of the things that I will research in the next project is what is the right way of creating an upgradeable facetted contract. I have read about some approaches but have not decided on what the way to go actually is.
One of the more interesting lessons came when I tried to implement random events into the game. Once in a while, a window will popup in the game, giving you an unique opportunity. After testing this feature extensively on rinkeby, releasing it fantom mainnet resulted in really high gas fees for the resulting transaction, called: "claimRandomEvent". Initial research showed that the high gas fees occurred when the transaction was expected to fail. Diving deeper into the issue, it showed that the transaction failed because the transaction was always processed after the event occured. Which led me to believe that my client was constantly behind the chain. It turned out it was, after implementing websockets, this issue was resolved and the game was now nicely in sync with the chain.
The issue however was not gone.
Turns out that one of the things to consider when going to the mainnet is the speed at which your transactions are picked up from the transaction pool. As the timing of this transaction was really important I needed to manually set the gas price to ensure that it would be processed with high priority. This seems obvious, but it is an interesting detail when remembering how testnet differs from mainnet.
Keep it simple
Another obvious tip is to reduce complexity in each contract. As contracts are public, they are quite vulnerable. Reducing complexity (and testing) are the best safety mechanisms. Moreover using standardized functionality is paramount to making a safe application. The contracts provided by OpenZeppelin are absolutely awesome.
Make sure to program an update strategy. When I just released the game, a bug was found within 24 hours and I had to upgrade the game. I was very glad I had some functionality in place to be able to upgrade the main contracts. You do not want to have nothing in place when the need arises to actually perform an upgrade to the contracts you have deployed.
Think of a way to involve players
I believe that DAO's are among the most intriguing concepts of the crypto space. The move to distribute governance tokens for players is a great way to get some involvement during the development of the game. Especially when combined with out of the box apps like snapshot.js.
Aside from the necessity to involve players, another thing I learned is that those players are very welcome when you deploy your application. It seems that while you can test a lot, actual game experience on main net is difficult to test. So one of the final things I learned and I would actually recommend is a closed beta on mainnet. Many game mechanics turn out a bit different than you actually imagine. Running a private beta on mainnet will teach you a lot about how people actually play the game.
Have fun while learning!!
I learned a lot more while developing this game! But the best thing is to enjoy the ride and have some fun during one of these projects.