ADR-4: Collections architecture in L1 & L2

More details about this document
Latest published version:
https://adr.decentraland.org/adr/ADR-4
Feedback:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on githistory.xyz

Context and Problem Statement

Collections will be key in the Decentraland ecosystem. To bring more scalability and reduce costs the L2 will be seen as the main chain, and L1, as the gateway for collectors to use/buy/sell tokens in other platforms.

L1 could be seen as Ethereum mainnet and L2 any other sidechain EVM compatible as Matic or xDai.

Each collection follows the ERC721 standard. Every token transferred between layers will keep a reference of itself in the main chain:

This document presents 2 alternatives on how to manage the collections between L1 & L2.

Alternatives

Alternative 1: Exact Collections' replication

clusterL2 L2 clusterL1 L1 Mainnet factory_l2 Factory L2 collection_l2_1 Collection 1 (data) factory_l2->collection_l2_1 collection_l2_2 Collection (data) factory_l2->collection_l2_2 collection_l2_3 Collection (data) factory_l2->collection_l2_3 collection_l2_4 Collection (data) factory_l2->collection_l2_4 collection_l2_5 Collection (data) factory_l2->collection_l2_5 collection_l2_6 Collection (data) factory_l2->collection_l2_6 bridge_l2 Bridge L2 bridge_l1 Bridge L1 bridge_l2->bridge_l1 collection_l2_1->bridge_l2 collection_l2_2->bridge_l2 collection_l2_3->bridge_l2 collection_l2_4->bridge_l2 collection_l2_5->bridge_l2 collection_l2_6->bridge_l2 factory_l1 Factory L1 collection_l1_1 Collection 1 factory_l1->collection_l1_1 mint collection_l1_2 Collection factory_l1->collection_l1_2 collection_l1_3 Collection factory_l1->collection_l1_3 collection_l1_4 Collection factory_l1->collection_l1_4 collection_l1_5 Collection factory_l1->collection_l1_5 collection_l1_6 Collection factory_l1->collection_l1_6 bridge_l1->bridge_l2 bridge_l1->factory_l1 collection_l1_1->bridge_l1 collection_l1_2->bridge_l1 collection_l1_3->bridge_l1 collection_l1_4->bridge_l1 collection_l1_5->bridge_l1 collection_l1_6->bridge_l1

Collections will be created through a Collection factory by users.

Collections in L1 will have the same address and the tokens will have the same id that they have in L2.

For example, if a user has the token with id 1 for the collection 0x326923D43226d9824aab694A3C1C566FeDa50AEb on L2, after transferring the token to L1, he will have the same token with the same id for the same collection in L1:

# L2:
- L2_Collection_1: 0x326923D43226d9824aab694A3C1C566FeDa50AEb
- token id: 1

- L2_Collection_2: 0x5B02123189F7F9251b5E57c390695c0d3B46e640
- token id: 1

# L1:
- L1_Collection_1: 0x326923D43226d9824aab694A3C1C566FeDa50AEb
- token id: 1

- L1_Collection_2: 0x5B02123189F7F9251b5E57c390695c0d3B46e640
- token id: 1

L2 to L1

L1_Collection_1L1_CollectionL1_FactoryL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserL1_Collection_1L1_CollectionL1_FactoryL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserTransfer token_1 to L1Lock token_1Compute lockValidate lockProcess token_1 lockCheck if exist L1_Collection_1Deploy L1_Collection_1 (if not exist)Deploy L1_Collection_1 (if not exist)Mint token_1

L1 to L2

L1_Collection_1L1_FactoryL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserL1_Collection_1L1_FactoryL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserTransfer token_1 to L2Burn token_1Compute burnValidate burnUnlock token_1Transfer token_1Transfer token_1

Alternative 2: Minimalist Collection replication

clusterL2 L2 clusterL1 L1 Mainnet factory_l2 Factory L2 collection_l2_1 Collection (data) factory_l2->collection_l2_1 collection_l2_2 Collection factory_l2->collection_l2_2 collection_l2_3 Collection factory_l2->collection_l2_3 collection_l2_4 Collection factory_l2->collection_l2_4 collection_l2_5 Collection factory_l2->collection_l2_5 collection_l2_6 Collection factory_l2->collection_l2_6 bridge_l2 Bridge L2 bridge_l1 Bridge L1 bridge_l2->bridge_l1 collection_l2_1->bridge_l2 collection_l2_2->bridge_l2 collection_l2_3->bridge_l2 collection_l2_4->bridge_l2 collection_l2_5->bridge_l2 collection_l2_6->bridge_l2 factory_l1 Factory L1 (safeguard) bridge_l1->bridge_l2 collection_l1_1 Collection (pointers & ownership) bridge_l1->collection_l1_1 collection_l1_1->bridge_l1

Collections will be created through a Collection factory by users.

Collections in L2 will be represented by a sole and unique collection in L1. The id of each token must be unique inside a collection. To avoid token ids collision, the id of each token will be the result of applying a hash function to the original token data.

For example, iif a user has the token with id 1 for the collection 0x326923D43226d9824aab694A3C1C566FeDa50AEb and the token id 1 for the collection 0x5B02123189F7F9251b5E57c390695c0d3B46e640 on L2, after transferring the token to L1, he will have a token id: hash(0x326923D43226d9824aab694A3C1C566FeDa50AEb, 1) and the token id: hash(0x5B02123189F7F9251b5E57c390695c0d3B46e640, 1) for the collection 0xF2a7755CFC27cedcb2BB9C65bf7B7dB380B54d63:

# L2:
- L2_Collection_1: 0x326923D43226d9824aab694A3C1C566FeDa50AEb
- token id: 1

- L2_Collection_2: 0x5B02123189F7F9251b5E57c390695c0d3B46e640
- token id: 1

- L2_Collection_2: 0x5B02123189F7F9251b5E57c390695c0d3B46e640
- token id: 2

# L1:
- L1_Collection: 0xF2a7755CFC27cedcb2BB9C65bf7B7dB380B54d63
- token id: hash(0x326923D43226d9824aab694A3C1C566FeDa50AEb, 1)

- L1_Collection: 0xF2a7755CFC27cedcb2BB9C65bf7B7dB380B54d63
- token id: hash(0x5B02123189F7F9251b5E57c390695c0d3B46e640, 1)

- L1_Collection: 0xF2a7755CFC27cedcb2BB9C65bf7B7dB380B54d63
- token id: hash(0x5B02123189F7F9251b5E57c390695c0d3B46e640, 2)

L2 to L1

L1_CollectionL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserL1_CollectionL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserTransfer token_1 to L1Lock token_1Compute lockValidate lockProcess token_1 lockMint token_1

L1 to L2

L1_CollectionL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserL1_CollectionL1_BridgeL2_ValidatorL2_BridgeL2_Collection_1UserTransfer token_1 to L2Burn token_1Compute burnValidate burnUnlock token_1Transfer token_1Transfer token_1

Decision Outcome

Alternative 1

Pros

Cons

Implications

Alternative 2 ✅

Pros
Cons
Implications

Open questions

OpenSea (mainnet): opensea.com/mainnet/tokens/{collection_l1}/{hash(collection_l1_1, token)}
OpenSea (L2): opensea.com/matic/tokens/{collection_l2_1}/{token}
  # L2
  collection_l2_1.tokenURI(token_1) = https://peer.decentraland.org/collection_l2_1/token_1
  mapping(tokenId => string) tokenURI

  # L1
  collection_l1.tokenURI(hash(collection_l2_1, token_1)) = https://peer.decentraland.org/collection_l2_1/token_1

  mapping(tokenId => string) tokenURI

Participants

Date: 2020-10-13

License

Copyright and related rights waived via CC0-1.0. DRAFT Final