From the perspective of application developers, the UTxO model is fundamentally different from the account-based model. The account-based model is simple and offers developers high flexibility, especially if it is necessary to define complex execution logic. However, excessive flexibility comes at the expense of execution guarantees, resulting in system vulnerabilities and attacks. Working with the UTxO model is more complicated, but it offers developers (and therefore users) several advantages, namely determinism. Let's explain it in more detail.
The UTxO Model from the Perspective of Transactions
In the case of the UTxO model, a transaction can be perceived as a function that consumes one or multiple input UTxOs and produces one or multiple output UTxOs.
UTxOs that enter the transaction are immutable and, as we will show later, from the point of view of the application user it is possible to ensure exclusive access. During transaction validation, it is ensured that the value of input UTxOs is equal to the value of all output UTxOs. At the level of validation of all transactions in the block, it is possible to ensure protection against a double-spend attack, as each input UTxO can be consumed only once and completely. Each newly added block to the ledger defines a state transition regarding the ownership of UTxOs.
Transactions are inherently stateless. Validation of the transaction depends essentially only on the input UTxOs. It is possible to locally verify that the input UTxOs can be spent by a transaction (ie used). State transition is locally verifiable without dependence on any other global on-chain state.
It is possible to predict locally how a transaction will affect the on-chain state. In other words, off-chain logic (user or application) can make sure that the transaction will not fail if it is submitted to the network.
A transaction will almost certainly never fail if the user (or agent) has the exclusive right to spend the input UTxO. This is the case when Alice sends coins or tokens to Bob from her own wallet. Input UTxO cannot be spent by anyone else.
Let's look at the only possibility when a transaction can fail. This is basically limited to the case where multiple agents can spend the same UTxO. As we will show later, this can be the case with the liquidity pool.
In the picture, you can see how two agents are trying to construct a transaction. Both agents have the correct latest state of the ledger. Coincidentally, they chose the same input UTxO. Local off-chain validation will be successful. Both agents therefore submit the transaction to the network and assume that the on-chain validation of the transaction will also be successful.
However, each UTxO can only be spent once. Therefore, only one transaction will succeed and the other will fail.
In the image below, you can see that in the following block, only transaction 1 made it to the ledger. Transaction 2 failed.
As we have already explained, this state can only occur if users use an application in which UTxOs are shared.
Let's now imagine a regular decentralized exchange (DEX) using several liquidity pools. Each liquidity pool can be seen as a set containing several UTxOs with different values. Users who submit transactions in order to perform swaps essentially want to get a part of the liquidity (tokens) that are in the liquidity pool. They basically want to get one or more UTxOs from the liquidity pool. In other words, users can submit swap transactions (almost) in parallel and compete for liquidity.
The key point is the selection of input UTxOs for transactions. Agents must synchronize with each other if transactions are not to fail.
Cardano theoretically makes it possible to build such an application that ensures that user transactions never fail. Off-chain application logic (agents) must synchronize with each other. Thanks to this, it is possible to reserve a specific UTxO from the shared liquidity pool before submitting the transaction. In other words, local off-chain validation can ensure that a transaction will almost certainly not fail.
In the picture below, you can see that there is a mutual off-chain synchronization between the agents before the local validation of transactions. Each agent reserves a different UTxO, so both submitted transactions are very likely to pass on-chain validation.
Of course, it will only work if it is possible to reserve UTxO. It may also happen that no suitable UTxO will be available when the user tries to submit a transaction. In such a case, it is possible to wait (and not submit the transaction), or take the risk and wait if a suitable UTxO does not appear later. The details depend on the specific DEX implementation and user interface.
The EUTxO model contributes to the security and deterministic nature of Cardano. In this model, transactions are not dependent on user accounts or balances as in the case of an account-based model, but rather only on the UTxOs involved in the transaction. This means that for a given transaction, only the involved UTxOs are important, not the user accounts that have a global nature.
In the UTxO model, the balance of a specific account is basically just a list of UTxOs at addresses belonging to one owner.
Why the Account-Based Model is Indeterministic
Account-based blockchains are indeterministic since the effect a transaction has on the ledger is unpredictable. The reason is that user accounts are inherently mutable.
In the account-based blockchain, a transaction can be seen as a function that changes the balances of accounts. Each transaction involves the transfer of coins or tokens from one account to another, which changes the balances of those accounts.
The validation of transactions is dependent on accounts and their balances. This can lead to non-deterministic behavior, as the outcome of a transaction depends on the state of the blockchain at the exact moment they are included in a block.
The accounts can be seen as a shared resource in the system. This is because all transactions are processed by the entire network, and each transaction can potentially affect the state of any account in the system. This shared nature of accounts is one of the reasons why Ethereum and other similar blockchains are considered stateful blockchains.
Transactions in Ethereum can be considered stateful. The complete state of Ethereum describes the current status of all accounts and balances, as well as the collective memories of all smart contracts deployed and running in the EVM. The current state can be altered with transactions.
Let's go back to our example where two users (agents) are trying to submit a swap transaction to get part of the liquidity (tokens) from the liquidity pool.
It’s not possible to reserve a part of a specific balance for a transaction in the same way that you can reserve a UTxO in Cardano. If the transaction were able to reserve a part of the balance from the liquidity pool and subsequently not be included in the blockchain for a long time (perhaps due to a low fee), they would block the execution of further swaps.
In a way, individual applications are also dependent on each other, as the activity in the network affects the GAS cost. GAS cost affects the selection of transactions and their order in the block. This leads to non-deterministic behavior.
In the AMM model, liquidity pools are essentially reserves of two or more tokens locked in a smart contract. Users trade with these smart contracts rather than with each other, and rates are based on mathematical formulas.
In the Ethereum ecosystem, users essentially compete for the balance or liquidity in a given liquidity pool. When users submit transactions in parallel, the Ethereum network prioritizes transactions based on GAS fees. The higher the GAS fee a user is willing to pay, the higher the priority of their transaction. This means that transactions with higher fees will be processed first and will have the first chance to consume liquidity.
This competition for liquidity can lead to what’s known as GAS WARS, where users continually outbid each other’s GAS fees in an attempt to have their transactions processed as quickly as possible. This is one of the reasons why transaction fees on Ethereum can sometimes be high.
In the picture, you can see that two agents want to consume the same balance. Both agents see that the balance is sufficient for their transaction and therefore submit the transaction at approximately the same time. The first agent sets a higher fee than the second.
Submitted transactions are not guaranteed to succeed, but users basically have to take the risk and try submitting if they want to make a swap. A transaction with a low fee can be delayed and other transactions with a higher fee can be prioritized. Transactions with low fees may subsequently fail. The fee will be charged regardless of the final status. The user therefore pays for the swap attempt without guarantee that the swap will take place.
You can see in the picture that only transaction 1 succeeded because the agent set a higher fee. Transaction 1 drained such a large amount of liquidity from the pool that transaction 2 could not be executed. The second agent had to pay the fee even though transaction 2 failed.
As already described, agents cannot synchronize with each other and reserve part of the balance in the liquidity pool. Agents only respond to the state that is valid at the time they try to submit a transaction.
Non-determinism is also disadvantageous from the point of view of fairness because it provides opportunities for adversarial agents to abuse network vulnerabilities. Front-running attacks are known, where bots scan transactions in the mem-pool and look for suitable opportunities from which they can profit. If they find such transactions, they just need to submit a similar transaction with a higher fee.
In our case, this would mean that the transactions of both agents would fail, as the attacker would drain the entire liquidity from the pool only for himself.
In the case of Cardano, a similar attack would fail if there was an off-chain reservation system in which agents would be able to reserve a specific UTxO for themselves.
Developers like the account-based model because it is simple and easy to work with. Applications basically only work with balances. However, the downside is that transactions do not behave deterministically and can fail. This is due to the fact that between when the user submits the transaction and when it is executed, the global state of the system, i.e. the balance on the accounts, can change.
The UTxO model is more complex to understand and the selection of input UTxOs can seem somewhat cumbersome. It is easier to deduct an amount from an account and credit it to another account than to have to select multiple UTxOs and create new output UTxOs from them (including UTxOs that return part of the value back to the original address). Developers are forced to think about applications with parallelization in mind. They have to take care of the synchronization between the agents so that there is no contention problem. From the user's point of view, however, it is possible to create such applications that will behave deterministically. If the local off-chain validation passes, the on-chain validation will also pass.