Vitalik and Qi, QuarkChain’s CEO & Cofounder had an interesting discussion on Cross-shard DeFi Composability recently. Here’s the whole post and Qi’s reply:
Vitalik:
There has been concern recently about whether or not the “composability” property of Ethereum - basically, the ability of different applications to easily talk to each other - will be preserved in an eth2 cross shard context. This post argues that, yes, it largely will be.
What does sharding change?
Transactions within a shard could happen as before. Transactions between shards can still happen, and happen quickly, but they would be asynchronous, using receipts. See https://github.com/ethereum/wiki/wiki/Sharding-FAQ#how-can-we-facilitate-cross-shard-communication for more information. In general, workflows of the form “do something here that will soon have an effect over there” will be easy; workflows of the form “do something here, then do something over there, then do more things here based on the results of things over there, all atomically within a single transaction” will not be supported. Doing things of that form would generally require first “yanking ” the contract from the “over there” shard to the “here” shard and then performing the entire operation synchronously on one shard. However, as we can see from examples below, most use cases would not be significantly disrupted or could be trivially rewritten to survive in a cross-sharded model.
Tokens
The ERC20 standard would need to be modified. Tokens would be able to exist on all shards, and seamlessly move from one shard to another just like ETH. This can be done with receipts, in the same way that ETH is moved from one shard to another, we can move tokens from one shard to another. There are no fundamental difficulties here.
Composability example 1: Uniswap <-> Tokens
Nearly all DeFi applications are uses of composability, because tokens are a type of application and so any DeFi application that uses tokens is an application that interacts with another application. Let us look at Uniswap as an example. In Uniswap, a user sends some quantity of token A to a Uniswap contract, which sends some quantity of token token B back to the user. Uniswap requires strict dependency between all transactions that interact with it: the Nth transaction must be aware of the output of the N-1’th transaction, because this is how the price updating algorithm works.
Hence, the Uniswap contract would need to live on a single shard (there are designs for multi-shard Uniswap, but they are more complex). Users looking to trade would perform a 2-step procedure:
- Send their token A to the shard that Uniswap is on.
- Perform a trade with Uniswap as before (the transaction doing this would be combined with the transaction “claiming” the receipt from step (1), so it’s a single step)
- [Optional] If desired, move the token B that Uniswap gave them to some other shard.
Composability example 2: Lending on Compound (including cDAI etc)
Compound could also exist on a single shard (if Compound gets too popular, different instances of Compound representing different pairs of tokens can be put on different shards). Users with a token would move their token over to the shard the particular Compound instance is on, and (create | fill | bite) a leverage position as before.
Composability example 3: tokens inside L2 scaling solutions (Rollup, Plasma…)
Move your tokens to the shard the L2 scaling solution has a contract on. Deposit into the contract. Done.
Composability example 4: rDAI, gDAI, etc
Move your DAI into the [insert DAI flavor here] contract. Take [insert DAI flavor here] out, and move it to whatever shard you want. The [insert DAI flavor here] contract itself could just sit on the same shard as the Compound instance for DAI for convenience.
Composability example 5: Set Protocol
Move your tokens into the shard that the set protocol contract is on (different instances could be in different shards as in Compound). Send them into the set protocol contract, get out a set token, move the set token to whatever shard you want.
Composability example 6: oracles
Synchronous cross-shard transactions are not supported, and so the “call a contract and immediately see what the answer is” workflow would NOT work. Instead, however, you could simply provide a Merkle proof showing the value in the state of the contract on the other side in the previous block (or in the most recent block for which the application’s shard is aware of the oracle contract’s shard’s state root).
Composability example 7: non-fungible assets and markets
Non-fungible assets including NFTs, in-game assets, ENS names, MakerDAO CDPs, Compound positions, etc, can be “yanked” to other shards, where they can interact with other applications (eg. atomic swap markets, auctions) seamlessly as before.
Overlay tools (eg. Instadapp)
In general, overlay tools that use specialized smart contracts to interact with dapps would need to create contracts for each function that they support, that users could yank to a desired shard, and then use on that shard to perform any needed functionality as before.
Qi:
We have implemented a multi-chain/sharding blockchain network that supports most of the DeFi examples at the time being in QuarkChain . To be specific, the network has implemented the following features to support Cross-Shard DeFi composability:
Sharding-Aware Address Format
Current address = ETH address (20 bytes) + chain ID (2 bytes) + 2 bytes unused. When performing a transaction, both the sender and receiver must specify the full addresses so that the network could determine which chain the tx is initiated from and which chain the receiver (a user address or smart contract) will receive the transferred token. If the chain ID’s of the sender and receiver of a tx are different, then the tx is cross-shard tx.
Cross-Shard Movable User-Created Tokens
To support moving a user-created token between different shards, a user could create a native token with a unique token ID, and a transferTokenID field is added in a tx to indicate which native token is transferred. As a result, a cross-shard tx will move the user-created token by deducting the balance of a user-created token, create a receipt (we call it “deposit”) including the balance and transferTokenId to target shard, and the target shard will process the receipt and increase the balance of the transferTokenId of the receiver.
Note that if the receiver address is a smart contract, the processing of the receipt will automatically call the smart contract and if there is a refund, the corresponding token will be added to the sender’s address in the target shard (i.e., same ETH address but with target shard chain ID).
Currently, we don’t support moving contract-based tokens (e.g., ERC20) to different shards at the moment, but a user could easily create a contract that could automatically swap a contracted-based token to a native token and move it to any shard.
Example for Uniswap
Suppose a user with ETH address 0x1122…ff would like to swap token A in chain ID 1 to token B by a uniswap contract in chain ID 0 with address 0x2233…ff 0000 xxxx, a user will create a tx with
tx = {
sender_chain_ID: 1,
to: 0x2233..ff0000xxxx,
transferTokenID=tokenA,
value=number_tokenA,
data="uniswap_call_data (e.g., swap to tokenB)",
v,r,s=sigature of sender,
...,
}
The transaction will trigger the following steps:
1, Withdraw tokenA from sender account in chain 1
2, Send the receipt to chain 0
3, Chain 0 processes the receipt, calls contract 0x2233…ff0000xxxx. Upon the success of the call, the swapped tokenB will be returned to 0x1122…ff0000xxxx
After the tx, a user could move the tokenB from 0x1122…ff0000xxxx to another shard address own by the user (e.g., 0x1122…ff0001xxxx). A tool was developed to help users collecting all balances from all shards to one shard (www.qpocket.io).
Cross-Shard DeFi for Heterogeneous Shard Chains
The design allows the sender who has balance in a shard chain with different ledger models (e.g., UTXO) to participant in DeFi in other chains. The transaction basically contains two parts: 1, the part that unlocks the sender’s UXTOs in a UTXO chain; 2, the part containing information for calling target shard such as smart contract full address, refund address, transferTokenId, startgas, etc.
Note that all the features are available in mainnet except we are discussing the native token insurance model at the time being.
Further, notice that the network only aims to provide a practical system that already supports the examples in the original post by Vitalik. This means it will suffer from the same issues (e.g., calling multiple contract in different shards atomically) of the original idea as discussed in the thread because all the cross-shard tx calls are async.
Further solution to address the async issue may provide a shard chain that is dedicated for DeFi with DeFi optimized consensus/ledger/tx model. Actually, we are working with nuts on the idea.