World Computers and Real-World Computers for DeFi
Let us discuss the challenges related to atomic transactions over multiple canisters on the Internet Computer. There seem to be two camps of people here: Those who think that atomic transactions offered as a system service are required for realizing certain use cases, and those who think they are not. My personal opinion is that the more you think about it the more you converge towards the second line of thinking. Let me elaborate on this.
When coming from an Ethereum-biased world, one clearly will want transactions also on the IC. That’s just how the world must work. It is true that the Ethereum world, or the one of any synchronous blockchain, works like this: You have essentially one thread of execution and this makes it easy to devise a system with global world state and transactions over a sequence of actions.
The synchronous world (EVM)
In this synchronous world it is trivial to implement things like swapping tokens within a single transaction without ever needing to take custody beyond the duration of a single transaction of one side of the tokens of the swap. Also it is easy to implement a DEX where one can swap a token A to a token D, even if there exists no trading pair (A, D), by “routing” via intermediate tokens B and C when trading pairs (A, B) (B, C), and (C, D) are listed. And by packing all the trades required for swapping A to D into a single transaction, the use gets the guarantee that either the full chain of swaps is executed according to the user’s constraints, or it is not executed at all. In the case it is not, the user only incurs gas fees, but has no other risk, e.g., ending up with tokens B or C.
Also, flash loans can be implemented in such a world with ease if one understands the execution environment like the EVM sufficiently well: A user (or their smart contract acting on their behalf) can borrow funds from a liquidity pool, earn money by arbitrage trading with those funds, pay back the loan with interest, and still earn some profit. All of that is happening within a single transaction, i.e., if anything goes wrong, e.g., money is lost during the arbitrage attempt, the transaction can be aborted, the loan has never been issued, the arbitrage loss never incurred, and thus there is no risk for the user. It’s a little time machine. That is, flash loans allow for doing financial transactions in a riskless fashion, which would not be possible in the real world. Only the gas fees for the transaction would need to be paid by the user.
Use cases like multi-hop swaps in a single transaction or flash loans are not possible in the real world. They are only possible in an artificial environment like an EVM-based blockchain because such environment comprises essentially the equivalent of a single computer realized as a replicated state machine, with a single execution thread and a global state space. The protagonists of this model (implicitly) postulate that a single computer is enough for the whole world. I.e., in terms of scaling you can only scale up, not out. If you would ever need to scale beyond the boundaries of what can be done within a single single-threaded machine, you would have to leave the model of synchronous execution, because your world state and execution would be split across more than one machine. This would mean to embrace asynchronous communication between those shards and thereby moving towards an asynchronous architecture and leaving the realm where multi-hop transactions and flash loans can be implemented as outlined above.
The asynchronous world (IC)
An asynchronous architecture like the IC comprises many independently-operating subnets where each subnet is its own blockchain. All state-changing invocations between smart contracts are asynchronous, incurring short latencies for intra-subnet calls, and longer latencies for inter-subnet calls. Welcome to the asynchronous model of execution for blockchains!
In the asynchronous model of the IC you currently do not have inter-canister transactions that span canisters of the same or different subnets. You neither have those in the real world. Thus, the IC still closely models what you can do in the real world and the real-world financial system. So almost every financial service of the real world will be implementable on the Internet Computer. Exceptions will be highly-specialized things like high-frequency trading which will not be implementable in the same way as in the real world just because of a blockchain having a block time of one or more seconds and HFT operating on a very different timescales on real-world centralized exchanges. And even less so it works in the same way as in the real world on EVM-based blockchains with their higher block latencies.
Let’s now look at a common example of a real-world service being implemented on the IC: A decentralized exchange as the blockchain equivalent of a centralized exchange. In an EVM-based blockchain an exchange is mostly implemented through the mechanism of an AMM for the reasons of compute and memory efficiency, as both compute cycles and memory is scarce in the EVM world (Remember, the world must share one computer for all their computational needs!). On the IC, one can easily implement a full-blown order book exchange that much more closely resembles the real world of financial services than an AMM. Notable advantages are that it resembles the concept of two parties exchanging assets with each other, which is the core concept behind an exchange, as well as slippage losses not going to arbitrage traders, i.e., this premium of the AMM world not having to be paid by the users.
Let’s next have a look at the more concrete implementation of the actual asset exchange: Different users (or market makers in the traditional sense) have placed orders and thereby created liquidity in the order book that others users can now trade against. This liquidity needs to be under custody by the exchange, that is, the corresponding assets (tokens) have been transferred to the exchange either using a direct ledger transfer or by the user allowing the exchange to transfer the tokens itself. Either way works, one constraint is that the order can be listed in the order book only once the tokens are under custody of the DEX. The approve-way is the one known from ERC-20 and the EVM world and is maybe the more convenient one.
Now let’s assume a user wants to place a spot order, i.e., buy tokens at market price. Again, the user can send their tokens via a transfer call to the corresponding ledger or approve the DEX to make the transfer on the user’s behalf. Once the tokens are on the DEX’s account, the actual exchange can take place: The DEX code matches the user’s order with the order book and finds one or more matching orders. It then computes how much of the target asset the user receives and updates internal accounts to update the state w.r.t. the swap. The important thing is that the actual exchange can happen atomically (in the scope where it matters, the rest of the world still moves on asynchronously at the same time, but this is not a problem) because the DEX canister can execute transactions atomically. The user can request the payout of the target tokens at any point or place further trades with them. This is just how an exchange in the real world would do it. An implementation of an order book exchange has been presented in yesterday’s DeFi workshop by DFINITY’s Tim and Eero.
This example shows that there is no need for system support for atomic transactions over multiple canisters to realize an exchange that closely resembles a real-world exchange as this can be done by regular canisters without any issue. It’s important to note that there is a difference to how things are done in a typical EVM-based DEX implementation, but we can implement a much more real-world exchange than on most other chains. Importantly, there is no weakening of the trust model by the DEX having custody of the funds for some time as it is a smart contract that people can publicly audit and that they need to trust anyway when using the DEX.
If one wants, an AMM-based DEX can be implemented easily on the IC as well that is much closer to what you know from Ethereum than an order book DEX. Let’s have a look at how a swap can be implemented here. Let’s assume the liquidity pool has been populated with tokens by liquidity providers, those tokens are under custody of the AMM canister much like they would be under custody of the AMM smart contract on an EVM chain. When a user now wants to make a trade on the AMM, there are two options how this can be implemented:
(1) The user makes a payment to the AMM first which brings the funds under custody of the AMM for a short duration and then places the trade. Once the trade is executed against the liquidity pool, the AMM computes the amount of the target asset the user receives and initiates a payout of the target tokens to the corresponding token ledger. The actual trade is computed in an atomically-executing thread of execution of the canister up to and including the initiation of the payout of the target tokens.
(2) The user approves the AMM to make transfers on their token account on the ledger of the source token of the trade. Then the user places the trade, the AMM initiates the transfer, and once the tokens have been credited to the AMM, it executes the trade as above atomically and initiates a transfer of the target tokens back to the user.
This model is very similar to how it is done on EVM chains, main differences are the following:
Token transfers are asynchronous and incur a latency, multiple seconds for Xnet transfers.
The AMM has custody over the source token for a short period until it initiates the transfer back out. We do not use the concept of a system-level transaction. We achieve the same outcome with the AMM on the IC as with one on an EVM chain, but with a slightly different implementation. I would like to claim that having the tokens under custody for a short time by the smart contract is not a practical issue that would make the model less powerful or less DeFi. It does not make any difference to the user.
Looking at DEXs where you can swap a token A to a token D via tokens B and C as further above on the Internet Computer: This cannot be directly implemented as in the synchronous world as we do not have those global transactions that could be reverted. That again reflects the real world. The implementation on the EVM as an atomic transaction is only possible because of the unrealistic assumption that the world’s DeFi can be handled by a single computer with a global state space and single-threaded execution, which, of course, does not scale at all.
But we can also implement this on the IC, just in a way that more closely resembles how this would be done in the real world. Options are:
(1) Implement the currency pairs all within a single canister and do it atomically therein. This does not work for Inter-DEX-multi-hop swaps of course and constrains scaling out.
(2) Just execute the swap optimistically with the risk of it getting stuck in an intermediate token the user does not want. That’s how the real world works for this scenario.
(3) Layer additional financial instruments on top as suggested in private communication by @timo which allows the user to insure themselves against volatility for a fee. This models also how the real-world financial system could address this.
We can see that also this use can be handled on the IC, even in a way much closer to how the real world works.
I do not want to claim that inter-canister atomic transactions across subnets would not be helpful in certain circumstances. E.g., they might help simplify the implementation for canister authors, but they come with a major complication: An atomic transaction that spans multiple canisters on different subnets needs to “lock” the assets concerned in the transaction, thereby incurring an opportunity cost for the canister holding the asset. This opportunity cost would need to be factored into the transaction model as a fee that the initiator of the transaction would need to pay. This fee would need to cover the opportunity cost in order for a transaction model to make sense from an economic perspective. This will make transactions (much) more complex than on EVM chains.
An inter-canister transaction could be implemented by a canister that offers it as a service. The canister could be run by a DAO. The security properties of this would be essentially the same as for a system-level transaction offered directly by the IC. But a canister might be the better place to implement the economic semantics of the transaction outlined above.
From the above elaboration, my hypothesis is that most interesting scenarios can be implemented on the IC in a way much closer to how the real world works. Some things, like flash loans are inherently not implementable the same way they work on EVM chains, just because this contradicts inherently the properties of the asynchronous architecture that the IC is. The question of whether we need transactions as a system service is a secondary one: They can always be implemented by a canister and offered as a service to users. I am looking forward to a discussion with you on this!