There is another important difference between Substrate's runtime and Ethereum smart-contracts. It's an ability to "pack" several calls to different contracts into one, atomic transaction. For Ethereum it's a very common pattern, there are many cases, when user deploys his own contract, that performs several DeFi operations in one call. The best example - usage of flashloans. In Ethereum a user's contract, for example:
- calls some contract, "flashloan giver"(for example AAve Lending pool (contract))
- passing callback data along with the call
- AAve contract gives the tokens to user's contract address and calls the callback
- user's contract use received tokens to:
- perform one call to some other contract (DEX, lending protocol)
- perform second call to some other contract (DEX, lending protocol)
- …
- user's contract returns his flashloaned tokens back to the AAve contract
- AAve contract checks if all tokens was returned
- reverts the whole transaction if something is wrong
All these steps are packed in one atomic call. In Substrate such a construction doesn't work. There is a possibility to use
utility.batchAll to pack several extrinsics in one sequential and atomic call, but the execution of these extrinsics(calls) will be isolated. This removes many attack vectors that are common in Ethereum, but at the same time, it does not allow for constructions like flashloans, which enable market makers to have super-flexible trading solutions. With flashloans a trader can start with a single token on his balance (for example WETH), borrow almost any token only for the time of the single transaction, perform the trade and return his funds back to WETH, adding also the "slippage" check (transaction is profitable, of reverted).
While Substrate doesn't have native packed calls design like in Ethereum, Substrate runtime has a possibility to run EVM inside, allowing
almost full duplication of EVM functionality. Substrate has a public
pallet_evm, which fully emulates EVM using
SputnikVM, but there can be much more native support of EVM. An excellent example is
Moonbeam.network, which allows users to interact with Moonbeam using the same wallets, client-side software, the format of addresses, deployment logic, and more, as in Ethereum. This network has XCM ability, enabling interaction with other parachains.
It is critical to mention the word "
almost" in "
almost full duplication of EVM functionality" while considering the security between EVM and lower-level implementations. Applying changes on two levels may lead to unsynchronized data, and this part of the code requires careful inspection. These problems typically arise in patterns of contract deployment, destruction, operations with account nonces, and relationships between native blockchain tokens/functions and their representation on the EVM side. It's related not only to "
EVM-on-[your virtual machine]"", but also to L1 <-> L2 interactions between L1 and L2 blockchains. Good examples of such problems: Optimism Infinite Money Duplication
Bugfix or Avalanche precompile
bug.