Let me share my though on this:
Each L2 maintains an “Exit Tree” This tree is a merkle tree where elementts can only be added and cannot be removed. This merkle tree contains entries of this type:
Entry Id: This is the key of the merkle tree, it’s incremntal and mantained by the wrapper manager.
Type: NFT_Exit
Original NFT: X
Original Rollup: A
Destination Rollup: B
Destination Owner: O2
The consistency of this Exit tree is warranted by the wrapper manager. The NFTs are locked in this smart contract in case they are original from this L2, or just burned if they are wrappers of NFT’s of other chains.
The hash of this exit tree is published in L1 when a batch is forged. (Or one week after the batch is forged in the case of optimistics).
Actually, a smart contract in L1 will maintain a merkle tree with ALL the Exit trees of all the L2 rollups. Let’s call it “Global Exit Tree”
The root of this “Global Exit Tree” is sent to all L2s. In the case of the zkRollup this can be a public input of the processing circuit.
In the L2s, this “Global Exit Tree” root is accessible. This can be done by adding it to the L2 state every time a batch is forged.
This should be enough to proof in L2 the authenticity of the transfer and withdraw the original NFT or create a wrapper in case it’s a foreign NFT. Of course nullifying that entry so that it cannot be used again.
Goodness of this protocol:
- You don’t need to proof the full track of the different chains it has been traveling.
- It can work the same way with ERC20 tokens just adding a value in the leaf.
- In the case of ERC20, it avoids having multiple wrappers of the same token in the same chain.
- This protocol can also be extended with inter L2 smart contract message communication. The leaf would say “Smart contract XXX is saying MsgY” and this msg will be available in the other L2.
- The same mechanism can be used for L1-L2 and L2-L1 transfers.