Web3 is predicated on the notion that individuals can own assets on the internet.
From DeFi, to Sovereign Identity, to Decentralized Autonomous Organizations (DAOs), every Web3 use case depends on digital assets of value - tokens; combined with self-executing rules on how those assets can be used - smart contracts, to incentivize decentralized communities of node-runners, developers, and users to deliver Web3 products and services.
With tokens and smart contracts being the core of Web3, the capabilities a smart contract platform gives its developers to make them must be one of its most defining features.
Those capabilities are provided by a platform’s Virtual Machine (VM), or execution environment. This is the layer of logic within a smart contract platform’s protocol that tells nodes how to execute a transaction. Anything built on top of a smart contract platform must follow the VM’s rules, dictating how tokens, smart contracts and transactions can be constructed.
But having surveyed almost 1,000 Web3 builders over 2019-2021, the tools provided by VMs today are inadequate. It takes developers years to become competent enough to then spend up to 90% of their time on the validations and testing required to make secure DeFi. Even then, billions of dollars of hacks still occur annually. New tools are needed if DeFi is to live up to its promise of a radically better financial system.
This is the first in a series of articles that explores the capabilities provided by VMs, comparing various shortcomings and solutions.
As assets are the core of Web3 and the primary purpose of any smart contract platform, we start by grouping VMs on the capabilities they provide to represent and manage assets. These are:
We then assess those VMs against how well they:
- represent Accounts & Tokens so that these are intuitive and secure;
- provide developers standard Asset Logic so they don’t have to keep reinventing and sometimes breaking the wheel;
- understand Transactions so they are safe and composable.
The Comparison
This first article compares:
- the most common category of VM: Messages only; vs
- a new approach that adds an additional Resources Finite State Machine (FSM) and Full Asset-Oriented Features.
If you don’t fully understand this table and supporting diagrams, these are explained further down this blog post.
The Explanation
Messages only
The Ethereum Virtual Machine (EVM) demonstrated to the world how tokens and smart contracts could be built on a public decentralized ledger. It did this by allowing anyone to build a self-contained machine - a smart contract - that contained the following:
- data
- rules on how that data can be updated as part of a transaction, i.e. smart contract logic.
Very quickly, developers worked out how to build tokens out of these two things:
- data - a list of accounts and balances to represent who owns a token
- data - anything else that may need to be recorded and updated, e.g. the privileged accounts that can modify the smart contract
- rules - how those accounts and balances and any other data can be updated, i.e. the methods and functions that form smart contract logic.
Every token and every smart contract on Ethereum is built by each developer, from scratch. The EVM is a blank canvas with limited in-built tools.
To ameliorate this, EVM developers converged on standards, such as ERC-20, that defined the interfaces that a smart contract should contain (what methods and functions should accept and return) and recommended implementations for how to do this. Libraries containing these can be downloaded, copied, and pasted into new smart contracts.
But this is done entirely off-ledger, as the Ethereum platform does not know that these standards or libraries exist. Any small modifications can sometimes have disastrous results, so developers have to understand every piece of logic in their smart contracts - whether imported from a library or not - to make sure the contracts are secure.
So why is this category of virtual machine called “Messages only”?
As a token is a list of accounts and balances inside a smart contract, it’s not possible to ever “send” a token somewhere. USDC can only ever live inside the USDC smart contract. SHIB can only ever live in the Shiba contract.
This means that if a user wishes to execute a transaction that involves more than one token, messages must be sent to the smart contracts for each token. Messages are the EVM’s only capability for transferring assets. It’s messages only.
We can see in the above diagram that a user submits a transaction to a Decentralized Exchange (DEX) smart contract to swap 30 Token A for 15 Token B. The DEX then sends separate messages to the Token A and Token B smart contracts requesting balance changes to effect the swap.
Following Ethereum, nearly every other smart contract platform has followed this same approach for tokens and smart contracts. This includes all the platforms that leverage the EVM, such as Avalanche, Fantom, BSC, Polygon or layer 2 networks such as Arbitrum and Optimism; as well as Near, Polkadot, Cosmos, and Solana - each with their own take on how this should be done.
Let’s now see how this category of virtual machine stacks up against the three criteria.
Accounts & Tokens
A1. What is an account?
🔴 An account is a balance entry for a given public key in a smart contract, repeated for each token held.
A2. What is a token?
🔴 A token is a list of balances for public keys, stored in a smart contract governed by a developer’s smart contract logic.
A3. How are tokens transferred?
🔴 Messages are sent to/from smart contracts to request that they update their internal list of balances.
A4. Can your tokens be sent without permission?
🔴 As a token is just a lineitem in someone else’s smart contract, if the developer still retains privileged access to the smart contract, they could change your balance inside it without your permission. Users would have to read through every line of code to verify whether this is possible or not.
A5. Can you receive tokens without permission?
🔴 Yes. Anyone can send you tokens without your permission as your account is just a lineitem in a list of account-balances in someone else’s smart contract.
This is one reason why it’s so difficult to code secure smart contracts, as you have to always account for the risk that a hacker can deposit tokens in your account outside of your application’s standard process, which can ruin calculations that leverage that balance.
Example hacks or bugs due to this include:
A6. Requires “approving” contracts to spend your tokens?
🔴 Yes. Users have to “approve” contracts such as Uniswap to spend your tokens on your behalf. This is a common attack vector for many hacks today.
Example hacks or bugs due to this include:
A7. Do apps keep virtual caches of their balances in other contracts?
🔴 Yes. Some applications have to keep track of their account-balances in other contracts i.e. reserve caches, adding an extra layer of complexity to make secure.
As anyone can send tokens to anyone’s address directly, this can sometimes ruin internal accounting algorithms, e.g. a liquidity pool becomes imbalanced.
Example hacks or bugs due to this include:
A8. Are authorizations limited to just addresses?
🔴 Yes - making it very difficult to transfer access rights and build complex permissioned applications.
Example hacks or bugs due to this include:
Asset Logic
Assets are not complex. They have universal properties no matter what the asset is, such as assets:
- should be owned by someone or something and can be allowed to be transferred
- should not be spent twice
- should not get lost or go missing during a transaction - they should net to zero.
However, message only platforms do not provide this standard logic to their developers. Developers are entirely responsible for implementing this logic themselves, again and again, every time they deploy a new token in a smart contract.
L1. Who implements asset logic?
🔴 Smart contract developers are entirely responsible for implementing all asset logic. Mistakes in any token smart contract can result in hacks or exploits, and any token smart contract may contain code to exploit users.
Example hacks or bugs due to this include:
L2. Is asset logic standardized?
🔴 No. Every contract has bespoke asset logic, lessening composability and increasing the chances for things to go wrong.
Example hacks or bugs due to this include:
Transactions
T1. Are users in control of their transactions?
🔴 No. Users can’t stipulate the outcome of a transaction. They have to trust the smart contract’s execution.
Message only VMs do not understand the assets that are contained in their smart contracts. To the VM, the asset is just a piece of data that must obey the smart contract’s logic.
Because of this, users can’t tell the VM what must happen in a transaction or else fail the transaction. Users are reliant on the smart contract’s logic only which can sometimes go wrong.
Example hacks or bugs due to this include:
T2. Are transactions blind signed?
🔴 Yes. Users sign transactions “blind”, not knowing what they’re signing, which hackers can exploit.
Message only VMs do not understand the assets that are contained in their smart contracts. To the VM, the asset is just a piece of data that must obey the smart contract’s logic.
Because of this, the VM can’t present what the transaction does to the user, so users sign transactions “blind”.
Example hacks or bugs due to this include:
T3. Can you call multiple contracts directly in one transaction?
🔴 No. Users can only directly call one contract in a transaction. Complex transactions require their own smart contract which can send long chains of calls downstream to other contracts.
This makes smart contracts incredibly difficult to make secure, as developers have to contend with complex logic that routes messages downstream, and downstream again. Developers have to ensure they understand all the permutations around how this logic interacts with multiple other smart contracts.
Example hacks or bugs due to this include:
T4. Is re-entrancy disabled?
🔴 No. Re-entrancy is a vital enabling feature which results in massive complexity and endless DeFi hacks and exploits.
Re-entrancy is when a smart contract is called twice or more in a transaction. This makes developing secure smart contracts much more difficult, as developers have to worry about the ordering of the logic in their smart contracts. If any logic is ordered incorrectly, this can result in hacks and exploits.
Example hacks or bugs due to this include:
Conclusion
Virtual machines that rely only on messages require developers to be fully responsible for:
- defining Accounts & Tokens themselves, as the platform doesn’t intrinsically understand what an asset is.
- creating all Asset Logic themselves, so developers keep having to redeploy this same logic in their contracts each and every time, with the slightest mistake resulting in hacks and exploits.
- dealing with complex and uncomposable Transactions, as the VM doesn’t understand what the transaction is doing in asset-terms.
Messages + Resources FSM + Full Asset-Oriented Features
The philosophy behind asset-oriented smart contract platforms is that on public decentralized ledgers, it’s all about assets. These VMs still allow smart contracts to send messages to one another, but they also have additional capabilities as articulated below.
An asset-oriented virtual machine inherently understands what an asset is, and provides features to easily and safely create and manage assets. This saves developers massive amounts of time as they’re not building assets from scratch. It also makes DeFi and Web3 far more secure, as the VM predictably handles how assets behave.
But first, let’s explore the concept of “resources” and Finite State Machines (FSMs).
Resources Finite State Machine (FSM)
A resource is an object that represents an asset. Resources have “physical” like properties, in that they can be transferred between the smart contract components that own them.
To create a token or transfer it between accounts, no code is necessary. You ask the VM to create or transfer your token through native function call (or via API). This significantly reduces the chances for things to go wrong and alleviates the burden on developers to create the logic that does this.
Here we can see 30 Token A being “physically” transferred from our user to someone else.
Below we can see what it looks like swapping 30 Token A to 15 Token B with a DEX (or for a more complete diagram showcasing all the core features, see the main Asset-Oriented diagram at the top of this blog post).
A Finite State Machine (FSM) is the part of the VM that governs how resources behave. FSMs are typically used for mission-critical systems where correct results must be guaranteed. The FSM guarantees that resources:
- should be owned by someone or something and can be allowed to be transferred
- should not be spent twice
- should not get lost or go missing during a transaction - they should net to zero.
Full Asset-Oriented Features
With the VM natively understanding what an asset is, this means you can introduce some nifty asset-oriented features:
- Self-sovereign Accounts & Assets, which enable capabilities such as asset-based authorizations
- Fully native Asset Logic, making DeFi easier to program and far more secure
- More composable Transactions, as the VM provides standards around how assets should move, enabling smart contracts to more easily talk to one another.
Accounts & Tokens
A1. What is an account?
🟢 An account is an individual smart contract “component” on-ledger that holds vaults of tokens.
This is more intuitive as you would expect that your account holds all your tokens, as opposed to your tokens being represented as account-balance lineitems spread across many smart contracts, as is the case for message only VMs.
A2. What is a token?
🟢 A token is a “physical” object stored in “vaults” inside smart contract components governed by platform (VM) rules.
A3. How are tokens transferred?
🟢 “Physical” tokens are transferred between vaults via buckets.
A4. Can your tokens be sent without permission?
🟢 As tokens are native platform-level resources, users can easily see a token’s permissions through a simple platform-enforced flag, e.g. if a token is “recallable”. If the token isn’t recallable, as users directly custody their own tokens in their own smart contract component, users are in complete control of their tokens and cannot be sent without their permission.
A5. Can you receive tokens without permission?
🟢 As accounts are components that directly hold tokens, it is possible to configure them to control which tokens they can receive.
This capability would have contributed towards preventing the following hacks or bugs:
A6. Requires “approving” contracts to spend your tokens?
🟢 Approving smart contracts is no longer necessary as assets are custodied in user’s smart contract components directly.
This capability would have contributed towards preventing the following hacks or bugs:
A7. Do apps keep virtual caches of their balances in other contracts?
🟢 Smart contracts maintaining a “virtual cache” of their balances is no longer necessary as assets are custodied in smart contract components directly and can control the tokens that can enter the component.
This capability would have contributed towards preventing the following hacks or bugs:
A8. Are authorizations limited to just addresses?
🟢 No. Authorizations are controlled by “badges” - NFTs that can be transferred between smart contract components, allowing for complex permissioned applications.
This capability would have contributed towards preventing the following hacks or bugs:
Asset Logic
L1. Who implements asset logic?
🟢 The VM handles all asset logic so dev time is spent on features and functionality, not validations and testing, and users can trust all asset behavior.
This capability would have contributed towards preventing the following hacks or bugs:
L2. Is asset logic standardized?
🟢Yes. The VM standardizes asset logic, improving composability and reducing chances for things to go wrong.
This capability would have contributed towards preventing the following hacks or bugs:
Transactions
T1. Are users in control of their transactions?
🟢 Yes. A “transaction manifest” allows users to specify the relevant results of a transaction, or the transaction doesn’t happen.
This capability would have contributed towards preventing the following hacks or bugs:
T2. Are transactions blind signed?
🟢 No. Users are presented with a transaction that directly describes asset flows so the user can understand what they are signing.
This capability would have contributed towards preventing the following hacks or bugs:
T3. Can you call multiple contracts directly in one transaction?
🟢 Yes. The transaction manifest allows users to call an arbitrary number of contracts in an atomic transaction and directly specify asset movements between them. No more deploying smart contracts just to create composed calls.
This capability would have contributed towards preventing the following hacks or bugs:
T4. Is re-entrancy disabled?
🟢 Yes. Re-entrancy is disabled as better solutions are available.
As the transaction calls each smart contract component in turn, there is no longer a need for re-entrant calls, which makes developing smart contracts hazardous as even the slightest mistake in the ordering of logic can result in hacks.
This capability would have contributed towards preventing the following hacks or bugs:
Conclusion
Virtual machines that have in-built Resources FSMs and Full Asset-Oriented Features significantly improve both user and developer experiences. This is because:
- Accounts & Tokens are inherently understood by the platform. They are no longer created in smart contracts.
- Asset Logic is handled by the VM, so developers can’t make the mistakes that lead to so many hacks, and only have to worry about business functionality.
- Transactions become highly composable as the VM passes native assets between smart contract components.