Ethereum’s invention of smart contracts running on a decentralized blockchain allowed us to imagine for the first time a world where DeFi (decentralized finance) has remade the global financial system to be as open and innovative as the internet itself. But perhaps the greatest barriers to actually reaching this world are the technical limitations of the way DeFi smart contracts must be written today. Developers need better – much better.
In this article, I’ll discuss how the development paradigm offered by Ethereum – and virtually every other smart contract platform – falls far short of the needs of global-scale DeFi; and I’ll discuss how a truly easy, safe, reusable, and composable development paradigm points the way toward Radix’s “asset-oriented” Radix Engine and Scrypto smart contract language.
12 years on from the invention of blockchain technology, DeFi has emerged as its most important and revolutionary use. The ability to securely manage financial assets of real value on a decentralized network means nothing less than the first steps of replacing a financial system that is inherently monopolistic with a better one that is open, democratic, and ceaselessly innovative.
This is the potential, but imagine what it really takes to remake global finance in a democratized model at the scale of hundreds of trillions of dollars and billions of users. It means millions of developers with millions of great ideas building better financial products and services. It means a system where the dApps (decentralized apps using smart contracts) that those developers write can offer just as much functionality at the same level of security that we’re used to today – or better – at unlimited scale and low cost on a decentralized network.
Yet DeFi today, and its developer community, are barely a blip on this scale. What’s holding back a world of developers from seeking all of the opportunities DeFi should offer?
It should be obvious that creating a DeFi developer ecosystem of this vast scope requires a highly specialized development paradigm. But today’s smart contracts – conceptualized on Ethereum in 2013 before anyone knew that global-scale DeFi was the problem to solve – have failed to deliver what developers need to take DeFi to mass adoption. And virtually every smart contract platform since has followed the same fundamental approach to smart contracts. Most have focused purely on improving scalability, without considering the issues that have made smart contracts unready to scale up in the first place.
What’s needed and how do today’s smart contracts fall short?
There are four things absolutely required of the development paradigm before a future world of global-scale DeFi begins to be possible. The way developers build smart contracts must be easy, safe, reusable, and composable. Here’s what I mean.
Any developer with a great DeFi idea must be able to start building and get to a deployed implementation as quickly as possible. This doesn’t mean just an easy “hello world”, nor just a quick path to their first deployed dApp. What’s important is how quickly a developer can come up the learning curve to confidently build and deploy a complex, featureful, and highly secure dApp that does real business.
If the development paradigm is easy enough, it opens up a world of developers who can seek the opportunity of building better financial products and services. It opens up the hiring pool for entrepreneurs who have the next big idea. And it means there is no barrier to developers implementing big, audacious ideas that can truly make the financial system work better for everyone.
Today, the learning curve for Solidity (Ethereum’s primary smart contract language) is years long to reach a “DeFi ready” level of expertise. Something as conceptually simple as “create a token” means deploying a bespoke smart contract that implements asset-like behavior from scratch. The responsibility is entirely on the developer for even the most basic, common functionality. Even worse, often smart contract development requires detailed understanding of how the platform operates, with high stakes if the developer doesn’t fully grasp it.
The result is an extremely small community of experienced DeFi developers, a hugely inadequate hiring pool for entrepreneurs that limits what they can create, and DeFi dApps that are as elementary as possible to minimize the risk of expensive exploits.
Which leads us to our next requirement...
Not only must building dApps be easy, but the result must be confidently trusted to correctly manage many millions of dollars.
Today, we hear from Ethereum DeFi developers that they typically spend only 10% of their time building core functionality and 90% trying to make it safe for deployment. And even then, we see frequent DeFi hacks and exploits resulting in millions of dollars of unrecoverable losses.
This isn’t a symptom of bad developers - it’s the result of a bad development paradigm. Every DeFi application is concerned with the correct management of assets and ensuring only authorized users can do the correct things. But today’s development paradigm forces the developer to implement the very concepts of assets and authorization from scratch without a safety net. The developer must then layer these bespoke implementations with their own dApp’s logic – and safely integrate with other dApps that are burdened in the same way.
The result is that developing virtually any production-ready dApp rapidly becomes a mass of unwieldy code that is extraordinarily difficult to analyze for safe asset management and authorization. The opportunities for exploitation are nearly impossible to avoid.
To reach the scale of global finance, developers need to be able to leverage the work of others. Mature solutions are built on the shoulders of the work of thousands of other developers who have already provided great solutions to recurring problems. The open source software movement has proven that code designed for open reusability is immensely powerful.
But we can’t just be content with open source code. We must take advantage of the power of a decentralized network to serve as an open, shared resource where proven solutions can be reused by others directly on the network itself – rather than just copied off-ledger and redeployed. Reusability must be a feature of the platform to massively accelerate the ability of developers to confidently create more complex dApps. This would not only accelerate the development of experienced developers, but would let common things like issuing a new asset to be done without writing any new code at all – a near-zero learning curve. Today there is no such reusability in DeFi.
The result is that Ethereum is full of redundant code, standards are slow to emerge and adapt to needs, and dApps become ever more complex to build. This in turn further amplifies shortcomings of development ease and code safety.
The ability for dApps to connect together is the lifeblood of DeFi, even today. Financial products and services are never isolated islands; their value comes from the ability to combine them together freely and instantly and a decentralized network should be able to do this a thousand times better than the walled gardens of traditional finance ever could by the ability to “compose” dApps together, at will, transaction by transaction.
And indeed the basic composability of Ethereum dApps is in large part what has enabled DeFi in its current form.
However, looking to the future, we see problems. Current composability is limited by the fact that all functionality on the platform is held in standalone smart contracts (for the same reasons that give us the problems with ease, safety, and reusability). Nothing is universal – not even the assets that are the subject of all finance. As more and more dApps are composed together, development difficulty and opportunities for safety failures don’t just add up - they multiply.
In fact, composability is even being reduced, or virtually eliminated, by changes to many DeFi platforms attempting to improve poor scalability – itself a major challenge to DeFi adoption. Even “scalable” network concepts that retain the possibility of composing dApps together do so by increasing the complexity for the developer. Composability must be an automatic feature of the platform, not yet another problem to be solved by developers and adding complexity to their code.
But are these problems with today’s DeFi development paradigm really so bad? Are today’s smart contracts broken or merely a work in progress? An example of how DeFi works on Ethereum today illustrates just how dire the situation is.
Let’s look at a DeFi dApp that conceptually is quite simple, Uniswap. This is what it does:
That’s it! But to simplify the picture even further, let’s look just at the swapping part. You might imagine that the Uniswap smart contract works something like a simple little machine:
A Trader has some A tokens in their account, they send them to the Uniswap smart contract, the contract does a little math using the pool of A and B tokens it owns to figure out the A/B exchange rate, and it sends the right amount of B tokens back. Surely for something this simple, the smart contract implementation must work roughly like this, right?
Not even close.
Here is a greatly simplified view of how just this one simple smart contract call works on the real Uniswap smart contract on Ethereum:
What in the world is going on here?
First, Ethereum has no inherent notion of “tokens”, so Token A and Token B are really just a pair of standalone ERC-20 smart contracts that each hold a little internal list of balances. We’re never really sending tokens around - we’re just sending messages to the methods of various smart contracts. The Trader doesn’t actually hold tokens in their account, as we imagine; they simply have balances listed in those smart contracts associated with their private key. (In a way this is replicating the financial system of today with separate, siloed balance sheets representing accounts!)
This means that the transfers of A and B tokens take the form of messages sent to those smart contracts by the Uniswap contract, since it’s doing everything for the user. And because Uniswap’s A and B reserve pools are just entries in those other smart contracts’ balance lists, Uniswap needs to keep and update its own internal cache of the current A and B balances that must be updated at each call to make sure they’re still correct for use in calculating the A/B exchange rate.
Also, if you’ve used Uniswap, have you ever wondered why you have to submit a transaction to “approve” a token before you can trade any of it? The reason is the pink line in the diagram above. To work, Uniswap has to do the sends of both A and B tokens on your behalf – so a separate “approve” transaction is required to tell the Token A ERC-20 contract “hey, Uniswap is allowed to send my A tokens wherever it wants”. Seriously! (Don’t give approval to a malicious or poorly-programmed dApp or your tokens are gone!)
Finally, note that the Uniswap smart contract is internally keeping track of the balance of its LP Token and has the same interfaces that the A and B ERC-20 contracts do. That’s because the Uniswap smart contract is, bizarrely, itself an ERC-20 token contract. It’s the LP token ERC-20, with all of the trade logic, trading methods, and data that has to be managed for trading are lumped on top of the token logic, methods, and data in the same smart contract.
The example of Uniswap shows just the beginning of the complexities that a developer must carefully handle when trying to implement DeFi apps on today’s smart contract platforms. And I’m not cherry picking an unusual example; Uniswap is generally regarded as one of the most well-implemented smart contracts on Ethereum.
This is exactly the kind of complexity that starts ramping up the learning curve for the new developer – and multiplying the opportunities for exploits that lose real money. And it only gets worse as dApps are composed together; imagine taking the Uniswap diagram above and combining it with those of other dApps and their internal interfaces, message passing, caches of data held in other smart contracts, and more.
Is it any surprise that developing smart contracts today fails to be easy, safe, reusable, or composable? The current smart contract paradigm forces this convoluted madness on every developer and is the cause of many of the problems and barriers severely limiting DeFi growth.
What’s the solution? Compare those diagrams above again. We need a dApp development paradigm where developers can build Uniswap as we intuitively imagine it, not as the smart contract paradigm forces us to.
The development platform that can deliver this paradigm will make dApps massively easier to build and simultaneously vastly more safe because the developer won’t be forced to carefully craft a dense tangle of counter-intuitive code to get the functionality they want. If that platform also allows code written in this new paradigm to be reusable and naturally composable (while providing unlimited platform scalability), we finally have a decentralized network platform ready for DeFi that can remake global finance.
This means rethinking smart contracts from scratch for the needs of DeFi – and that’s exactly what Radix has done with Radix Engine v2 and Scrypto. In the next article, I’ll discuss how Radix is finally giving developers a powerful asset-oriented development paradigm.
Early access to Scrypto and Radix Engine v2 are coming this year as part of Radix Alexandria. Alexandria will let developers experiment with creating, compiling, and interacting with Scrypto-based blueprints and components in a simulator environment running on their local machine. Deployment of blueprints and components to the Radix Public Network will follow in Radix Babylon, coming in 2022.