Saving $250,000/year and 3 months of development time
As a community-driven project, our team (for now) is not paid a traditional salary and relies on donations for compensation, which are not fixed nor certain. As a result, it is difficult to guarantee high standards of service and technology, but it’s essential for traders (and us!) that CivTrade is online live 24/7!
Without a team enabling our services as products to be what they are and reliably accessible, traders would have to constantly monitor the price of the assets they want to trade, hoping for the market to reach their desired price before manually closing their positions. This would create a terrible user experience, so pushing the trade execution process onto users was not an option at all for the Civilization team and developers of CivTrade.
Limit orders enable traders to specify the price at which they wish to buy or sell an asset and have it executed automatically at that price, with nothing required of the trader other than placing the order.
One option would have been to run an off-chain server to trigger the trade-close process. However, this would have required developers to build, manage, and deploy a DevOps solution from scratch. Not only would this service have been centralized and prone to downtime, but it would also have added significant development time and costs that could instead have been focused on building new products and features. When we ran the numbers, the in-house business case just simply didn’t add up.
Comparing in-house DevOps automation with Chainlink Keepers
We realized that building a comparable solution in-house to address the problem that Chainlink Keepers would immediately solve would require a substantial investment of time and money:
- 2+ People – one developer to build and upgrade the system and one system administrator to monitor and maintain it. Although paying the salaries of the team on a monthly basis, ensuring a professionally run operation from day one so you can payout for an entire year would require significant upfront budget lock-up. Assuming a $100,000/year salary per person, plus benefits, we estimated a minimum of $250,000 for the in-house route to start.
- 2+ Datacenters. two redundant locations for high availability, plus a third for disaster recovery, plus additional development and staging environments, would make the total server cost scale-up 5x. If production was run on a higher performing, higher cost stack, and disaster recovery/dev/staging on cheaper servers (which is not ideal), the cloud-computing bill to keep the in-house system up 99.9%/24/7 would still run up to $3,000+ per calendar month.
- Downtime. Having just two people would mean support would be 9–5 on working days only. Forget about 99.99% availability. Even with 5 datacenters, issues are bound to happen at times when support teams are not around! We estimated up to 1% system downtime in-house, versus achieving 99.99% by leveraging Chainlink Keepers’ ability to spread the administration overhead over multiple projects and therefore guarantee much better service. And we can also sleep soundly at night, with one less thing to worry about.
- Investment. As a community-funded start-up, we prefer to pay as we scale, rather than having to fundraise money upfront. Since Chainlink Keepers don’t require ponying up any money upfront, we love them even more.
- Time. We conservatively estimated it would take at least 3 months to set up a stable in-house solution. Building systems, even when you have the money to do it, takes time and distracts attention from other priorities. Since it only took us a couple of days to read the Chainlink docs and set up the code required to go live, the choice gave us a huge speed boost!
So, for us, running the numbers showed that the choice was a no-brainer, and therefore we immediately got down to integrating Chainlink Keepers. Here is how we did it.
Civilization is able to greatly improve uptime through its integration with Chainlink Keepers: moving towards full decentralization, Chainlink Keepers enables CivTrade to offer traders automated limit order execution with enhanced security, reliability, and performance for near real-time trade execution.
Civilization chose Chainlink Keepers as our decentralized transaction automation service to help close trades when CivTrade-specific conditions are met. This provides CivTraders with confidence that all their limit order positions are continuously monitored and optimally executed without any manual interactions from users or the Civilization team.
The Chainlink Network is the most widely adopted and time-tested oracle network in the DeFi industry. It has a flawless track record of providing high-quality services to blockchain applications. - DexMan, Lead Dev
Decentralized exchanges allow anyone to trade. Civilization’s integration of Chainlink Keepers helps us open the door to people who want to experience the market without the need for the help of third parties.
Chainlink Keepers have ample documentation, making them the easy-to-use solution for automated smart contract execution. We just had to write a dedicated smart contract with two main functions:
- 1.Verify in real-time if our execution conditions have been met: “is any CivTrade ready to close?”
- 2.Trigger the execution of our smart-contract: “immediately close all the CivTrades that have just been filled by the market”.
Changes required to our core CivTrade contract? Zero. Technically, we only had to write the new contract, and add it to the authorized list of blockchain addresses with authority to close positions — alongside the trader and the multi-sign CivTrade admin.
Our simple dedicated Keeper smart contract automates what otherwise could have been done manually, had a team of analysts been available 24/7 to monitor each trade (which clearly would be impossible, or very impractical to say the least). For every new block mined by each of our CivTrade-supported blockchains, currently Ethereum + Polygon (besides our test chains Kovan and Mumbai), Chainlink Keepers check our trigger conditions, and when they are met, close the relevant trades.
Chainlink Keepers describe the standard for these two functions, called checkUpkeep and performUpkeep.
The CivTrade Keeper contract function: checkUpkeep
Within the checkUpkeep function, our implementation checks whether each trade within the range has been filled by the market. Ranges are a partitioning mechanism to load balance activity across different Keepers, helping avoid running out of gas if the number of trades to be monitored grows too large. Currently, we run up to 1,000 trades through each Keeper, but we estimate a max capacity load in excess of 10,000 CivTrades per Keeper, or even more. This will keep us running for quite a while, as there’s no limit to the number of Keepers we can switch on. See the above section on cost scaling: this system grows with us!
The triggered() function checks if a CivTrade is ready for closing: this means that the asset being sent for trading has been entirely swapped into the other asset, so the pair (initialAmount,0) has become (0,targetAmount). For example, for a 1 ETH -> 200 LINK trade, initially the trader sends (1 ETH,0); the trade will complete when the position has become (0, 200 LINK).
Whenever at least one CivTrade is ready for closing, the variable upkeepNeeded will be set to True by the checkUpkeep function, which will also write into performData (abi-encoded) the list of all CivTrades to be closed as soon as possible.
Chainlink nodes constantly call the checkUpkeep function, on each and every block. Whenever upkeepNeeded evaluates to True, then the nodes will call the performUpkeep function.
The CivTrade Keeper contract function: performUpkeep
performUpkeep checks again that each CivTrade from performData is ready to be closed, because anyone can call this function.
We can’t trust the input data at face value, but check it again before execution. Once the triggered() condition is validated again, the CivTrade is immediately closed. Whereas checkUpkeep doesn’t actually do anything per se, performUpkeep can close positions, therefore for additional security reasons we made it pausable.
To activate this new Chainlink Keepers-compatible contract, we simply registered it online, following the Chainlink Developer Documentation. We set a 1-million gas limit, in case our performUpkeep needs to execute multiple closes at the same block; and set checkData for the first 0–1000 trades. Voila; our Upkeep is up and running.
Our Chainlink Keepers mainnet Upkeep
We had to repeat the registration process for Polygon, and ta-da, CivTrade went cross-chain!
For security and scalability reasons, we implemented the following checks:
- Keeper contract is pausable by our multi-sign admin.
- checkUpkeep waits for an interval of at least 5 blocks (about 1 minute) after the last performUpkeep was triggered, to avoid clogging or repeat closes.
- 1,000 CivTrades can be monitored by each Upkeep, to prevent out-of-gas errors; we can register any number of new Upkeep as we scale.
Civilization is a successful community-driven project with a dedicated and highly skilled dev team, to which the Chainlink Labs team provided truly world-class support around the clock: crucial to our success. A big shout out to Michael Stone and the whole Chainlink Labs team: not only do they promptly reply to any of our questions 24/7, but also they help with go-to-market technical support. We appreciate the incredibly high level of support that the Chainlink Labs team offers: it truly makes a difference!
While CivTrade continues to expand to all the blockchain networks supported by Uniswap v3, we look forward to Chainlink Keepers’ continued support of new networks, so that all traders can benefit from CivTrade’s reliable and decentralized trading toolkit.