How I Built the ICO Platform Behind a 1 Million Presale 👨🏻‍💻
Guest post by my friend and business partner Mark Engel
A month ago, I built a platform to collect funds for ConcertVR’s (Goodstuff-Media) Pre-ICO. We reached our funding goal of 1 million EUR in 4 days.
This is the story of how I went from first meeting to launch in under a month.
How I Got Involved
Feb 2018 Sebastian, from Goodstuff-Media, asked to have a call. He’d just got a recommendation from my friends at Taikonauten to talk to me about technical questions regarding an ICO.
Sebastian had a good plan, but was still unsure who would be building the code behind the ICO. He’d talked to a couple of teams but didn’t have a good feeling. They couldn’t give him simple answers to his questions, which made him doubt whether he could trust them.
When we met, we clicked right away. He was super pragmatic, and I enjoyed explaining the technical aspects to him.
Goal: A system to collect funds. Secure and simple.
Making a Plan
There wasn’t much time to mess around. The date of the Pre-ICO was already fixed for a few weeks from then.
What we wanted was clear: A system to collect funds, which is secure and easy to use.
But there are many ways to build that. The best solution for Sebastian depended on the details. Who are the target contributors? Where and in which currencies do they want to pay?
Before I could advise him what to do, I wanted to know everything that he and his team had planned.
So I asked him to block a whole day and invite his marketing team and everyone else advising on the ICO. If someone couldn’t make it, we’d catch up with them afterwards.
Strategy Day
Sebastian and I set ourselves 3 goals for the day:
- Collect all the advice and opinions on what we needed for a successful ICO;
- Make a plan for how to build it;
- Explain the technical aspects in a way everyone could understand.
It worked out great. At the end of the day, we had a plan. I knew what I needed to build, and I could tell Sebastian how long it would take.
Among the things we decided were:
Collecting contributions in ETH and Bitcoin
People should be able to contribute in both Bitcoin and ETH. So a simple smart contract on the Ethereum platform wouldn’t be enough, since you can’t interact with Bitcoin from within the Ethereum ecosystem.
Referrals
The team needed a referral mechanism built into the platform. They had already set up deals with affiliates and needed to track and report to their partners funds that arrived from their referrals.
The problem with having only a single wallet
Initially, we considered having a wallet for Bitcoin and a wallet for ETH. It would have made things simple: Any contribution from an Ethereum wallet would receive our tokens in that same wallet. Anybody contributing in Bitcoin would submit an Ethereum wallet address and then receive the tokens there.
However, we learned that a lot of people want to send funds directly from an exchange, like Coinbase, Kraken, or Poloniex. If we always issued the tokens back to where the contribution came from, then in the case of ETH contributions coming through an exchange, our tokens would go to the wrong wallet: They would end up in the Ethereum wallet from the exchange, not the contributor’s wallet.
Unique wallets for every contributor
We wanted to keep things simple. First, simple solutions carry fewer risks. Second, they are less confusing for contributors. In the end, we found a way for our whole purchasing flow to require only one input from the contributor: their email address.
The solution was to issue every contributor a unique wallet address.
How it worked:
- The contributor would give us their email.
- We would generate* a unique wallet address for them and save it with the email in our database.
- After a contributor sent their funds to their unique wallet, they would get a confirmation email.
- Every other question, like KYC and where to send the funds, we asked later via email.
*We issued the unique wallets with Bitcoinjs-lib, which implements the bips protocol. With that we derived a tree of key pairs from one master private key. That allowed us to create any number of sub-wallets which were all only spendable through the master key.
Security
You only have one shot at getting it right during an ICO. A small mistake might mean losing millions. I wanted us to be extremely confident in the security and stability of the system we launched.
I push rigorous testing for any software, but now it was even more important. Every function that could be unit tested was unit tested. Every functionality that depended on an external service (such as email) was integration tested. Using Heroku, we also had an extremely straightforward deployment process.
We also made our frontend as simple as possible and served only a static webpage. Something like Wordpress would have been too risky and exposed many possible vulnerabilities.
Checking the sum of contributions
Every time a new wallet was created we saved it in a PostgreSQL database. A process then checked our wallets’ current balance every 5 minutes. Due to API limitations at Etherscan and Blockchain.info, we could only check 20 wallets at a time. So we saved the last time a wallet was checked, and then always queried Etherscan for the balance of the wallets whose update time was the oldest.
Access
The private key for all the wallets was kept exclusively in a Trezor hardware wallet, which belonged to Sebastian. The ICO platform used a public key and was basically read-only: It could check which funds arrived in which wallets, but couldn’t do any transactions. This meant that only Sebastian had access to the funds.
The Day of the Pre-ICO
We did our Pre-ICO in February 2018. Our goal was to collect 1 million EUR in crypto funds within a week.
The official start of the ICO was midday in Berlin, at 12:00 CET on 14 February 2018.
5 minutes before launch, we changed an email template, which was not a problem thanks to our simple deployment process.
We met in our office and started to look at the contributions coming in. Everything ran smoothly. Contributor participation numbers where higher than anticipated!
That also meant that our script to keep track of the funds in the wallets couldn’t keep up. I upgraded the balance-checking process from running every 5 minutes to running continuously. We could safely deploy that change even during the ICO.
After a few hours, we had reached one-third of our funding goal.
4 days later, we hit the 1 million EUR mark.
Lessons Learned
Communication. Things worked smoothly because we took the time to get everyone in a room and discuss things in detail. By explaining the different technical options, we had the basis for a productive discussion and made sure we decided on the right solution.
So take the time to collect everyone’s ideas. In a field that’s this young, no one has all the answers.
And ask questions! If anything is unclear to you as a developer, ask. Since things are so critical, it’s important you are super clear on what the team expects.
Trust
Understanding each other is the basis for trust. With tight deadlines and a lot at stake, the team had to place a lot of trust in me. The better you can answer questions and the more upfront you are about all aspects of the system, the easier it will be for the team to trust you.
Keep it simple
Find the simple solution. Complexity makes you vulnerable. One reason the ICO went so smoothly is because we consciously removed from the funding process any step that wasn’t absolutely necessary. And don’t confuse the contributors.
Focus on security
Plan most of your time for writing tests and simplifying deployment. Minimize attack vectors by hosting a static page. Requirements might change at the last minute, and you want to be confident when you make a change.
We’d love to hear any feedback. If you’re looking for help with your own ICO, email us at ico [at] datarevenue.de
Watch out: In April Goodstuff-Media is following up its Presale with their ICO for the ConcertVR CVT Token.