Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Latest commit

 

History

History
714 lines (456 loc) · 14.3 KB

0010.md

File metadata and controls

714 lines (456 loc) · 14.3 KB
  DSP: 0010
  Title: LAND contract
  Author: Ignacio Mazzara 
  Status: Accepted
  Type: Standards
  Created: 2019-03-11

LAND contract

Table of Contents

Introduction

Every parcel in Decentraland's world is represented by a non-fungible token ERC #721 that is indivisible and unique. This registry is powered by a smart contract where it is defined all the information related to each parcel.

Abstract

Decentraland's most important digital asset is its LAND token. The world is divided into square parcels of LAND that act similarly to a domain name: the owner of a LAND can decide what to show inside the 3D experience, in very much the same way as the owner of "example.com" can decide what webpage to show when a browser connects to that domain.

The LAND token exists within a EVM blockchain (currently Ethereum). Decentraland is one of the first examples of the ERC 721 "NFT" token (the standard explicitly cites Decentraland and CryptoPunks as the first projects to experiment with this idea).

This document describes the structure, and the expected behavior and functionality of interacting components provided by the LAND contract also known as LANDRegistry contract.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 8174 when, and only when, they appear in all capitals, as shown here.

Compatibility

LAND is compliant with the ERC721 Ethereum standard, and implements the ERC721Base interface, as well as the ERC721Enumerable interface.

Its implementation could be find here.

Terminology

Parcel: the logical unit of land subdivision in the Decentraland's world. Each parcel may contain metadata formerly used to save its content.

LAND: a brand name for parcels.

Coordinates: x, y representation of the parcel.

Asset Id: token id of the parcel generated by encoding the x and y coordinates.

Estate: a group of parcels placed together.

Account: an Ethereum address

Design

Coordinates

The coordinates of a LAND parcel are its X and Y coordinates, using 128 bits to represent the (signed) coordinate.

The following are examples of coordinates:

X Y 256-bit Hexadecimal Representation
0 0 0x0000000000000000000000000000000000000000000000000000000000000000
-1 0 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000
1 -1 0x00000000000000000000000000000001ffffffffffffffffffffffffffffffff
-1 150 0xffffffffffffffffffffffffffffffff00000000000000000000000000000096
0 90 0x000000000000000000000000000000000000000000000000000000000000005a
150 150 0x0000000000000000000000000000009600000000000000000000000000000096

Contract

This contract was created using a proxy pattern which allows upgradability.

Roles

Proxy owner

The account owner of the LAND proxy contract.

Contract owner

The account owner of the LAND registry contract.

AuthorizedDeployer

Account allowed to create new parcels.

Owner

Account which is the owner of a specific parcel.

ApprovedForAll

Account which plays as a co-owner for all the parcels owned by another account. An account can has multiple ApprovedForAll

Operator

Account which plays as a co-owner for a specific parcel. A parcel can has only one Operator.

UpdateManager

Account that can update the parcel metadata of all of the parcels owned by another account. An account can has multiple UpdateManager

UpdateOperator

Account only allowed to update the parcel metadata. A parcel can has only one UpdateOperator.

Parcel Metadata

Every parcel has metadata which is used to represent its content (scene). The metadata has the following structure:

version,name,description,ipns

  • Version: number of the metadata version.
  • Name: Parcel name.
  • Description: Parcel description.
  • IPNS: ipns hash link to the parcel scene.

E.g: 0,"My parcel","Description",""

Dead Ping

To be defined.

Specification

Events

Update

Emitted when the parcel metadata changed.

Update(
  uint256 assetId,
  address holder,
  address operator,
  string data
)

UpdateOperator

Emitted when the parcel update operator changed.

UpdateOperator(uint256 assetId, address operator)

DEPRECATED: Transfer

Emitted when the parcel was transfered.

Events from block 4944642 to 5270587 have this topic:

Transfer(
  address from,
  address to,
  uint256 assetId,
  address operator,
  bytes userData,
  bytes operatorData
)

DEPRECATED: Transfer

Emitted when the parcel was transfered.

Events from block 5270587 to 6239536 have this topic:

Transfer(
  address from,
  address to,
  uint256 assetId,
  address operator,
  bytes userData
)

Transfer

Emitted when the parcel was transfered.

Events from block 6239536 to latest have this topic:

Transfer(address from, address to, uint256 assetId)

ApprovalForAll

Emitted when an account gives approval for all of their tokens to another address.

ApprovalForAll(address operator, address holder, bool authorized)

Approval

Emitted when an account gives approval a specific token to another address.

Approval(address owner, address operator, uint256 assetId)

OwnerUpdate

Emitted when the owner of the contract changed.

OwnerUpdate(address _prevOwner, address _newOwner)

EstateRegistrySet

Emitted when the EstateRegistry changed.

EstateRegistrySet(address registry)

Functions

Authorizations

setApprovalForAll

Set or remove an account as ApprovedForAll

setApprovalForAll(address operator, bool authorized)

isApprovedForAll

Get if an account is ApprovedForAll for a specific address

isApprovedForAll(address assetHolder, address operator) return (bool)

Approve

Set an account as Operator.
To clean the Operator, set it to the zero address.

function approve(address operator, uint256 assetId)

getApproved

Get the parcel Operator

getApproved(uint256 assetId) returns (address)

getApprovedAddress

Get the parcel Operator

getApprovedAddress(uint256 assetId) returns (address)

isAuthorized

Get if an account is ApprovedForAll or Operator for a parcel

isAuthorized(address operator, uint256 assetId) returns (bool)

setUpdateOperator

Set an account as UpdateOperator

setUpdateOperator(uint256 assetId, address operator)

updateOperator

Get the parcel UpdateOperator

updateOperator(uint256 assetId) returns (address)

isUpdateAuthorized

Get if an account is ApprovedForAll, Operator or UpdateOperator for a parcel

isUpdateAuthorized(address operator, uint256 assetId)

Transfers

transferFrom

Transfer a parcel to another address using the parcel's asset id.

transferFrom(address from, address to, uint256 assetId)

transferLand

Transfer a parcel to another address using the parcel's coordinates.

transferLand(int256 x, int256 y, address to)

transferManyLand

Transfer many parcels to another address using the parcels coordinates.

transferManyLand(int256[] x, int256[] y, address to)

safeTransferFrom

Transfer a parcel to another address using the parcel's asset id and checking if the destination account is a contract and implements OnERC721Received function.

safeTransferFrom(address from, address to, uint256 assetId)

safeTransferFrom

Transfer a parcel to another address using the parcel's asset id and checking if the destination account is a contract and implements OnERC721Received function with extra data.

safeTransferFrom(
  address from,
  address to,
  uint256 assetId,
  bytes userData
)

transferLandToEstate

Add a parcel to an Estate using the parcel's coordinates.

transferLandToEstate(int256 x, int256 y, uint256 estateId)

transferManyLandToEstate

Add a many parcels to an Estate using the parcels coordinates.

transferManyLandToEstate(int256[] x, int256[] y, uint256 estateId)

Creations

createEstate

Create an Estate with many parcels using its coordinates.

createEstate(int256[] x, int256[] y, address beneficiary)

createEstateWithMetadata

Create an Estate with many parcels using its coordinates and metadata.

createEstateWithMetadata(
  int256[] x,
  int256[] y,
  address beneficiary,
  string metadata
)

Metadata

updateLandData

Update the parcel metadata using its coordinates.

updateLandData(int256 x, int256 y, string data)

updateManyLandData

Update many parcels metadata using its coordinates.

updateManyLandData( int256[] x, int256[] y, string data)

landData

Get the parcel metadata using its coordinates.

landData(int256 x, int256 y) returns (string data)

tokenMetadata

Get the parcel metadata using its asset id.

tokenMetadata(uint256 assetId) returns (string data)

Utils

encodeTokenId

Encode the parcel coordinates to the parcel asset id.

encodeTokenId(int256 x, int256 y) returns (uint256)

decodeTokenId

Decode the parcel asset id to the parcel coordinates.

decodeTokenId(uint256 value) returns (int, int)

tokensOf

Get the parcels asset id owned by an account.

tokensOf(address owner) returns (uint256[])

landOf

Get the parcels coordinates owned by an account.

landOf(address owner) returns (int[], int[])

ownerOfLand

Get the parcel owner using the parcel's coordinates.

ownerOfLand(int256 x, int256 y)

ownerOf

Get the parcel owner using the parcel's asset id.

ownerOf(uint256 assetId) returns (address)

ownerOfLandMany

Get the parcels owners using the parcels coordinates.

ownerOfLandMany(int256[] x, int256[] y) returns (address[])

tokenOfOwnerByIndex

Get the parcel asset id by the owner index.

tokenOfOwnerByIndex(address owner, uint256 index) returns (uint256 assetId)

exists

Get is the parcel has owner using the parcel coordinates.

exists(int256 x, int256 y) returns (bool)

exists

Get is the parcel has owner using the parcel asset id.

exists(uint256 assetId) returns (bool)

supportsInterface

Get if the contract supports an interface.

supportsInterface(bytes4 _interfaceID) returns (bool)

proxyOwner

Get the owner of the proxy contract.

proxyOwner() returns (address)

totalSupply

Get the count of parcels created.

totalSupply()

authorizedDeploy

Get if an account is an AuthorizedDeployer.

authorizedDeploy(adderss operator) returns (bool)

balanceOf

Get the count of parcels owned by an account.

balanceOf(address owner) returns (uint256)

currentContract

Get the current implementation contract address.

currentContract() returns (address)

name

Get the name of the contract.

name() returns (string)

description

Get the description of the contract.

description() returns (string)

decimals

Get the decimals of the contract.

decimals() returns (uint256)

owner

Get the owner of the contract.

owner() returns (address)

symbol

Get the symbol of the contract.

symbol() returns (string)

estateRegistry

Get the current Estate registry contract address.

estateRegistry returns (address)

GET_METADATA

Get the GET_METADATA function selector.

GET_METADATA() returns (bytes4)

Ping

ping

Set the latest caller activity to now.

ping(address user)

setLatestToNow

Set the latest account activity to now.

setLatestToNow(address user)

latestPing

Get the latest activity of an account.

latestPing(address) returns (uint256)

Admin

assignNewParcel

Create a new parcel by its coordinates.

assignNewParcel(int256 x, int256 y, address beneficiary)

assignMultipleParcels

Create multiple parcels by its coordinates.

assignMultipleParcels(int256[] x, int256[] y, address beneficiary)

authorizeDeploy

Authorize an account to create new parcels.

authorizeDeploy(address beneficiary)

forbidDeploy

Forbid an account to create new parcels.

forbidDeploy(address beneficiary)

transferOwnership

Transfer the ownership of the contract to another account.

transferOwnership(address _newOwner)

setEstateRegistry

Set the Estate Registry contract address.

setEstateRegistry(address registry)

Limitations

As blocklimit limitation, every transaction which support many parcels manipulation may run out of gas. It is strongly recommended to divide the transaction in multiple ones to achieve the same.

From the above landOf and tokensOf may not work if the account is owner of more than 20 parcels.