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









clusterL1

L1 Mainnet


clusterL2

L2



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

sequenceDiagram
  participant User
  participant L2_Collection_1
  participant L2_Bridge
  participant L2_Validator
  participant L1_Bridge
  participant L1_Factory
  participant L1_Collection

  User->>L2_Collection_1: Transfer token_1 to L1
  L2_Collection_1->>L2_Bridge: Lock token_1
  L2_Validator-->>L2_Bridge: Compute lock
  L2_Validator->>L2_Validator: Validate lock
  L2_Validator->>L1_Bridge: Process token_1 lock
  L1_Bridge-->>L1_Collection_1: Check if exist L1_Collection_1
  L1_Bridge->>L1_Factory: Deploy L1_Collection_1 (if not exist)
  L1_Factory->>L1_Collection_1: Deploy L1_Collection_1 (if not exist)
  L1_Bridge->>L1_Collection_1: Mint token_1

L1 to L2

sequenceDiagram
  participant User
  participant L2_Collection_1
  participant L2_Bridge
  participant L2_Validator
  participant L1_Bridge
  participant L1_Factory
  participant L1_Collection_1

  User->>L1_Collection_1: Transfer token_1 to L2
  L1_Collection_1->>L1_Bridge: Burn token_1
  L2_Validator-->>L1_Bridge: Compute burn
  L2_Validator->>L2_Validator: Validate burn
  L2_Validator->>L2_Bridge: Unlock token_1
  L2_Bridge-->>L2_Collection_1: Transfer token_1
  L2_Collection_1->>User: Transfer token_1

Alternative 2: Minimalist Collection replication









clusterL1

L1 Mainnet


clusterL2

L2



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

sequenceDiagram
  participant User
  participant L2_Collection_1
  participant L2_Bridge
  participant L2_Validator
  participant L1_Bridge
  participant L1_Collection

  User->>L2_Collection_1: Transfer token_1 to L1
  L2_Collection_1->>L2_Bridge: Lock token_1
  L2_Validator-->>L2_Bridge: Compute lock
  L2_Validator->>L2_Validator: Validate lock
  L2_Validator->>L1_Bridge: Process token_1 lock
  L1_Bridge->>L1_Collection: Mint token_1

L1 to L2

sequenceDiagram
  participant User
  participant L2_Collection_1
  participant L2_Bridge
  participant L2_Validator
  participant L1_Bridge
  participant L1_Collection

  User->>L1_Collection: Transfer token_1 to L2
  L1_Collection->>L1_Bridge: Burn token_1
  L2_Validator-->>L1_Bridge: Compute burn
  L2_Validator->>L2_Validator: Validate burn
  L2_Validator->>L2_Bridge: Unlock token_1
  L2_Bridge-->>L2_Collection_1: Transfer token_1
  L2_Collection_1->>User: Transfer 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. Final