DSP: 0013 Title: Marketplace v2 contract Author: Ignacio Mazzara Status: Final Type: Standards Created: 2019-04-25
Every LAND and Estate in Decentraland can be exchanged for MANA by an mart contract which provides the ability to do a trustless and transparent atomic swap.
Digital assets (Non-fungible tokens) can be traded in exchange for MANA to increase the Decentraland economy.
Within this marketplace, new users will be part of the Decentraland ecosystem using their MANA to buy any token which follows the ERC721 Ethereum standard and the Decentraland Composable ERC721 standard.
The Marketplace v2 contract exists within an EVM blockchain (currently Ethereum).
This document describes the structure and the expected behavior and functionality of interacting components provided by the Marketplace v2 contract also known as the Marketplace 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.
With the marketplace v1 accepting only LAND to be traded, the creation of the Estates, the first Composable NFT, and the need of having and play with all the ERC721 tokens inside of Decentraland, made us thinking of creating a marketplace contract accepting every token which follows the ERC721 Ethereum standard and the Decentraland Composable ERC721 standard to be traded in exchange for MANA.
The Marketplace v2 contract is compatible with token which follows the ERC721 Ethereum standard and the MANA token.
Its implementation can be find here.
Order: NFT listing. Every order has its unique id generated by the block timestamp, NFT owner, id and the price.
Asset: NFT token which follows the ERC721 Ethereum standard.
Composable Asset: NFT token which is composed by others NFTs. E.g: An Estate is a composable NFT of LANDs.
Legacy NFT: NFT token supported on the marketplace v1.
Account: an Ethereum address.
This contract is upgradable, ownable and pausable.
It accepts only tokens which follow the ERC721 Ethereum standard for listing and the MANA token for buying.
The MANA contract is set at the contract creation stage.
The contract also needs to be created with a legacyNFTAddress
. This address is for the LAND token originally accepted by the marketplace v1 to continue supporting its methods.
The upgradability feature was dropped to a self-destructed contract which means that nobody can upgrade it.
The contract has an owner called contract owner which play as an admin. He can transfer its ownership, pause and unpause the contract.
The contract can stop accepting, cancelling and executing orders. The pause functionality can be actionable only by the contract owner.
The account owner of the Marketplace v1 contract.
OrderCreated
Emitted when an asset is listed for sale.
OrderCreated(
bytes32 id,
uint256 assetId,
address seller,
address NFTAddress,
uint256 priceInWei,
uint256 expiresAt
)
OrderCancelled
Emitted when an asset listing was cancelled
OrderCancelled(
bytes32 id,
uint256 assetId,
address seller,
address NFTAddress
)
OrderSuccessful
Emitted when an asset was successfully bought.
OrderSuccessful(
bytes32 id,
uint256 assetId,
address seller,
address NFTAddress,
uint256 totalPrice,
address buyer
)
AuctionCreated
Emitted when an asset of the legacy NFT was listed for sale.
The OrderCreatead
event will be emitted too.
AuctionCreated(
bytes32 id,
uint256 assetId,
address seller,
uint256 priceInWei,
uint256 expiresAt
)
AuctionSuccessful
Emitted when an asset of the legacy NFT was successfully bought.
The OrderSuccessful
event will be emitted too.
AuctionSuccessful(
bytes32 id,
uint256 assetId,
address seller,
uint256 totalPrice,
address winner
)
AuctionCancelled
Emitted when an asset of the legacy NFT listing was cancelled.
The OrderCancelled
event will be emitted too.
AuctionCancelled(bytes32 id, uint256 assetId, address seller)
ChangedPublicationFee
Emitted when the fee for listing was changed
ChangedPublicationFee(uint256 publicationFee)
ChangedOwnerCutPerMillion
Emitted when the fee for selling was changed
ChangedOwnerCutPerMillion(uint256 ownerCut)
ChangeLegacyNFTAddress
Emitted when the legacy NFT address was changed
ChangeLegacyNFTAddress(address legacyNFTAddress)
Pause
Emitted when the contract was paused
Pause
Unpause
Emitted when the contract was unpaused
Unpause
OwnershipTransferred
Emitted when the contract owner was changed
OwnershipTransferred( address previousOwner, address newOwner)
Migrated
Emitted when the contract was migrated.
Migrated(string contractName, string migrationId)
createOrder
Listing an asset with a desired price and expiration (Unix time).
createOrder(
address NFTAddress,
uint256 assetId,
uint256 priceInWei,
uint256 expiresAt
)
LEGACY createOrder
Listing a legacy NFT with a desired price and expiration (Unix time).
createOrder(
uint256 assetId,
uint256 priceInWei,
uint256 expiresAt
)
executeOrder
executeOrder(address NFTAddress, uint256 assetId, uint256 price)
Buy a listing for an asset. The price should match with the listed price and also the buyer should have at least that balance in MANA.
safeExecuteOrder
Buy a listing for a composable asset. The fingerprint and the price should match with the listed ones and also the buyer should have at least that balance in MANA.
safeExecuteOrder(
address NFTAddress,
uint256 assetId,
uint256 price,
bytes fingerprint
)
LEGACY executeOrder
Buy a listing for a legacy NFT. The price should match with the listed price and also the buyer should have at least that balance in MANA.
executeOrder(uint256 assetId, uint256 price)
cancelOrder
Cancel a NFT listing.
cancelOrder(address NFTAddress, uint256 assetId)
LEGACY cancelOrder
Cancel a legacy NFT listing.
cancelOrder(int256 assetId)
auctionByAssetId
Get the order by the asset id.
orderByAssetId(address, uint256)
auctionByAssetId
Get a legacy NFT order by the asset id.
auctionByAssetId(uint256)
publicationFeeInWei
Get the publication fee.
publicationFeeInWei()
acceptedToken
Get the accepted token address.
acceptedToken()
paused
Get whether the contract is paused or not.
paused()
ownerCutPerMillion
Get the fee for listing an asset in millions.
ownerCutPerMillion()
owner
Get the contract owner address.
owner()
legacyNFTAddress
Get the legacy NFT address
legacyNFTAddress()
ERC721_Interface
Get the 4 bytes hash of of the ERC721 Ethereum standard interface.
ERC721_Interface()
InterfaceId_ValidateFingerprint
Get the 4 bytes hash for the Decentraland Composable ERC721 standard interface.
InterfaceId_ValidateFingerprint()
setOwnerCutPerMillion
Set the fee for listing an asset.
setOwnerCutPerMillion(uint256 _ownerCutPerMillion)
setPublicationFee
Set the fee for buying an asset listed
setPublicationFee(uint256 publicationFee)
pause
Pause the contract
pause()
unpause
Unpause contract.
unpause()
destroy
Destroy the contract.
destroy()
transferOwnership
Transfer the ownership of the contract to another account.
transferOwnership(address _newOwner)
setLegacyNFTAddress
Set the legacy NFT address.
setLegacyNFTAddress(address _legacyNFTAddress)
This contract only accepts MANA in exchange for the assets listed.
Users need to approve their MANA on contract behalf. Therefore was a potential risk of stealing a lot of MANA if the contract can change its implementation because the contract can move user's MANA.