Deck ERC1155

The ERC1155 Deck contract allows for the wrapping of ERC1155s as Items, and for the burning of Deck-items ERC1155s to retrieve the original tokens.

Wrap

Before wrapping an ERC1155 token, check that it follows the usual ERC1155 standard. To be standard, it must

  • integrate the standard IERC1155 interface

  • have 0 or 18 decimals

  • have a safeTransferFrom/safeBatchTransferFrom function so that the token can be correctly wrapped and unwrapped

An ERC1155 can be wrapped in one of two ways:

  1. By using the mintItems function.

  2. By sending the token using the safeTransferFrom / safeBatchTransferFrom function to the ERC1155 Deck Wrapper contract, which implements onERC1155Received and onERC1155BatchReceived.

When wrapped, all ERC1155 IDs of the same token address generate the same Deck Item ID. So, for example, if you wrap two Adidas Originals, 2e18 Adidas Original Deck Items are minted, and they share the same Deck Item Id.

mintItems

function mintItems(CreateItem[] calldata createItemsInput, bool[] calldata reserveArray) external returns(uint256[] memory itemIds);

This function has two inputs:

  • CreateItem -> data for wrapping an ERC1155.

  • reserveArrays -> boolean value that expresses whether the wrap is to be reserved (true) or unreserved (false).

The lengths of CreateItem and reserveArrays must be the same; each CreateItem must correspond to its sequentially equivalent value in reserveArrays.

For each ERC1155 being wrapped, a CreateItem struct must be passed, as follows:

  • Header -> composed of address host, string name, string symbol and string uri. Pass as empty; these parameters are automatically populated by the contract. See here for more info.

  • collection -> encoded token address of the ERC1155 being wrapped.

  • id -> id of the ERC1155 being wrapped.

  • accounts -> receiver(s) of the Deck Item. Pass as address(0) to set as msg.sender, or pass as any other address(es).

  • amounts -> quantity of the ERC1155 to wrap. Must be expressed in 0 decimals if you're wrapping a 0 decimal 1155 token, or in 18 decimals if you're wrapping an 18 decimal 1155 token. For example, pass as 1 if wrapping 1 of a 0 decimal ERC1155; as 2 if wrapping 2 of a 0 decimal ERC1155; as 1e18 if wrapping 1 of an 18 decimal ERC1155; etc.

You can split and send different amounts to multiple accounts. The lengths of the amounts and accounts arrays must be the same; each amount value must correspond to its sequentially equivalent account value.

Example

Six Zerions (id 10) are wrapped by an address; the first three reserved, the other three unreserved.

CreateItem1

  • Header -> - host: 0x00.. , - name: " ", symbol: " ", uri: " "

  • collection -> 0x00000000000000000000000074ee68a33f6c9f113e22b3b77418b75f85d07d22

  • id -> 10

  • accounts -> 0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4

  • amounts -> 3

CreateItem2

  • Header -> - host: 0x00.. , - name: " ", symbol: " ", uri: " "

  • collection -> 0x00000000000000000000000074ee68a33f6c9f113e22b3b77418b75f85d07d22

  • id -> 10

  • accounts -> 0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4

  • amounts -> 3

reserveArray: [true, false]

Using the mintItems function, multiple different ERC1155 tokens can be wrapped in a single transaction by passing multiple CreateItem structs at once.

The mintItems function returns the created itemIds.

onERC1155Received

You can also wrap a token as a Deck Item by using the safeTransferFrom function to send the token to the ERC1155 Deck Wrapper contract, which calls the onERC1155Received function.

The data parameter of safeTransferFrom must contain the following encoded parameters:

  • Uint256 [] values -> the amount of newly wrapped Deck Items to send to each receiver address. The values must be expressed in 0 decimals (such as 1, 2, 3 and so on) if wrapping a 0 decimal ERC1155, or in 18 decimals (1e18,2e18 and so on) if wrapping an 18 decimal ERC1155.

  • Address[] receivers -> receiver(s) of the Deck Item.

The lengths of values [] and receivers[] must be the same; each value in values[] must correspond to its sequentially equivalent value in receivers[].

  • Bool reserve -> boolean value that expresses whether the wrap is to be reserved (true) or unreserved (false).

values and receivers are analogous to the amounts and accounts parameters of the mintItems function.

Example

2 Parallels are sent (id 10144) to be wrapped as Deck Items with reservations to the ERC1155 Deck Wrapper contract, using safeTransferFrom with the following encoded data:

  • Uint256 [] values -> 2

  • Address[] receivers -> 0x82465CB46506563f66285f18da7adD332e813A42

  • Bool reserve -> true

onERC1155BatchReceived

ERC1155s can also be wrapped as Deck Items by using the safeBatchTransferFrom function to send the tokens to the ERC1155 Deck Wrapper contract, which calls the onERC1155BatchReceived function.

This allows you to wrap multiple ERC115 ids of the same token address.

The data parameter of the safeBatchTransferFrom function must be a bytes[]. For each id being wrapped, each element of the array must contain the following encoded parameters:

  • Uint256 [] values -> the amount of the Deck Item (in 0 decimals) to send to each receiver address.

  • Address[] receivers -> receiver addresses for the Deck Item.

The lengths of values [] and receivers[] must be the same; each value in values[] must correspond to its sequentially equivalent value in receivers[].

  • Bool reserve -> boolean value that expresses whether the wrap is to be reserved (true) or unreserved (false).

Example:

2 Parallels (id 10144) are wrapped with reserve.

The holder address uses safeBatchTransferFrom to send the token with the following encoded data:

data1:

  • Uint256 [] values -> 2

  • Address[] receivers -> 0x82465CB46506563f66285f18da7adD332e813A42

  • Bool reserve -> true

Reserve

Unlike with ERC721 Decks, reservations can be made for a specified quantity of ERC1155s. Each reserve corresponds to a such a quantity.

When a quantity of ERC1155s is wrapped with reserve, only the address that wrapped it (i.e. the msg.sender of the mintItems/safeTransferFrom/safeBatchTransferFrom function) can unwrap and retrieve it for the following 10 days (in blocks). Each reserve corresponds to a struct:

struct ReserveData {
    address unwrapper;
    uint256 timeout;
    uint256 amount
}
  • address unwrapper -> msg.sender of the mintItems/safeTransferFrom/safeBatchTransferFrom function.

  • uint256 timeout -> blocks for which the ERC1155 is reserved. Equal to block.number + reserveTimeInBlocks, where reserveTimeInBlocks is the number of blocks that are estimated to correspond to 10 days.

  • uint256 amount -> quantity to be reserved of the specific ERC1155.

If, at any time during the reservation period, the unwrapper address transfers the Deck Item to another account, that account will be unable to unwrap it until the end of the 10 day reservation period, at which point it becomes unreserved and can be unwrapped by anyone.

A key reserveDataKey (bytes32) is created every time a reservation is generated.

To retrieve and reconstruct the corresponding reserveDataKeys, each time a quantity of ERC1155s is wrapped with a reserve, a ReserveData event is emitted:

emit ReserveData(from, tokenAddress, tokenId, amount, timeout, reserveDataKey);

Unlock Reservation A reservation can be ended without having to unwrap the token, by using the unlockReserves function:

function unlockReserves(address[] calldata owners, address[] calldata tokenAddresses, uint256[] calldata tokenIds, uint256[] calldata amounts) external;
  • address[] owners -> address of the unwrapper.

  • address[] tokenAddress -> address of the original ERC1155 to unlock.

  • uint256[] tokenIds -> id of the original ERC1155 to unlock.

  • uint256[] amounts -> reserved amount to unlock. Must be equal to the total reserved amount; you can't partially unlock a reservation.

You can use unlockReserves to unlock multiple reserves at once.

Unwrap

The unwrapping of Deck Items to retrieve the original ERC1155s can be done in either single mode, by using the burn function, or in batch mode, by using the burnBatch function.

Burn

function burn(address account, uint256 itemId, uint256 amount, bytes memory data) override(Item, ItemProjection) public
  • address account -> address of the Deck Item holder.

  • uint256 itemId -> id of the Deck Item to unwrap (burn).

  • uint256 amount -> amount of Deck Item to unwrap (burn).

  • bytes data -> data in bytes format that must contain the following encoded parameters:

- address tokenAddress -> token address of the original ERC1155.

- uint256 tokenId -> id of the original ERC1155.

- address receiver -> address that will receive the original ERC1155. Pass as address(0) to set as msg.sender, or pass as any other address.

- bytes32[] reserveDataKeys -> reserve key to be unwrapped. Pass as empty (0x00..) if unwrapping (burning) a quantity of unreserved ERC1155s.

- bytes data -> eventual optional data to perform a safeTransferFrom.

Example

1)

2 (in 18 decimals) Zerion Deck Items are unwrapped (burned) to retrieve 2 unreserved Zerions (id10).

  • account -> 0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4

  • itemId -> id of the Bored Ape Deck Item, for example 583149398095120659341456634

  • amount -> 200000000000000000000000000

  • data -> data = web3.eth.abi.encodeParameters( ["address", "uint256", "address", "bytes32[]", "bytes"], ["0x74EE68a33f6c9f113e22B3B77418B75f85d07D22", "10", "0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4", "0x00..", "0x"] );

2)

2 (in 18 decimals) Parallel Deck Items are unwrapped (burned) to retrieve 2 reserved Parallels (id10144).

  • account -> 0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4

  • itemId -> id of the Parallel Deck Item, for example 9717612899372047983059638622121

  • amount -> 200000000000000000000000000

  • data -> data = web3.eth.abi.encodeParameters( ["address", "uint256", "address", "bytes32[]", "bytes"], ["0x76BE3b62873462d2142405439777e971754E8E77", "10144", "0x998093DF3d61dDDae8F4a84e02e12c78b3751cC4", "0x66ca656de9e6ad847f83f20e17f774cef9394447dc3887c958f5426ae09b5730", "0x"] );

burnBatch

function burnBatch(address account, uint256[] calldata itemIds, uint256[] calldata amounts, bytes memory data) override(Item, ItemProjection) public

Using burnBatch, multiple Deck Items can be unwrapped at once—even multiple Deck Items from different Decks.

The function parameters are the same as the burn function, but with the following differences:

  • uint256[] itemId and uint256[] amount-> arrays of values; you can unwrap multiple tokens at once.

  • bytes data ->the data parameter in bytes format is an encoded value that represents a bytes[] (one for each Deck Item involved in the operation) containing the five parameters explained above in the burn section.

Regarding Reserves

  • Using burn/burnBatch, if you unwrap (burn) a reserved quantity less than your total reserved quantity, the entire reserve is automatically unreserved. For example, if your reserved amount is 10 and you unwrap 3, the other 7 tokens automatically become unreserved, and can be unwrapped by anyone.

  • If a reservation expires without having been previously unreserved, the corresponding reserveDataKeys must still be passed at the time of unwrapping. And since the reservation is expired but not yet dissolved, anyone can pass that key to unwrap the tokens.

When a Reservation becomes unreserved, partially or totally, a ReserveDataUnlocked event is emitted:

event ReserveDataUnlocked(address indexed from, bytes32 indexed reserveDataKey, address tokenAddress, uint256 tokenId, address unwrapper, uint256 amount, uint256 timeout);

Deck Items With a Total Supply <=1

Unwrap

If the total supply of a Deck Item ranges from 0.51 to 1 (in 18 decimals), keep in mind the following:

  • You can unwrap an ERC1155 by burning an amount of Deck Items between 0.51 and 1 in 18 decimals. This is in contrast to the "normal" situation where the total supply is >1, in which case you always have to burn 1e18 Deck Items for each ERC1155 that you want to unwrap.

Examples

1) ERC1155s wrapped Parallel id 10144, unreserved

Parallel Deck Item totalSupply 0.9e18

A Parallel Deck Item holder can unwrap one (id 10144) by burning at least 0.51e18.

2)

ERC1155s wrapped Parallel id 10144 & Parallel id 15255, both unreserved

Parallel Deck Items totalSupply 0.6e18

A Parallel Deck Item holder can unwrap one by burning at least 0.51e18.

If the total supply of an ERC1155 Deck Item ranges from 0 to 0.51, no one can unwrap it, because the Deck Item's totalSupply is < 0.51.

Wrap

When you're going to wrap an ERC1155 as a Deck Item, and the Deck Item's totalSupply is <1, you obtain 1e18-Deck Item total supply.

You have to pass 1 as amounts parameter of the mintItems/safeTransferFrom function whenever more of that ERC1155 is wrapped if it's an ERC1155 with 0 decimals or you have to pass 1e18-Deck Item total supply if it's an ERC1155 with 18 decimals.

Examples

1)

Parallel Deck Items totalSupply 0.3e18

When you wrap your Parallel, you obtain 0.7e18 Parallel Deck Item and you have to pass 1 as amounts parameter of mintItems/safeTransferFrom

2)

Parallel Deck Items totalSupply 0.1e18

When you wrap 2 Parallel ERC1155s, you obtain 1.9e18 Parallel Deck Items, and you have to pass 1 (receiving 0.9e18) as amounts parameter for the first one, and 1e18 for the second one of mintItems/safeTransferFrom.

Why Could a Deck Item's Total Supply Be <=1?

There are two possible reasons.

  1. You're either the first to wrap or the last to unwrap an ERC1155 as a Deck Item, and as a result the Deck Item's totalSupply is equal to 1e18.

  2. Holders of a Deck Item burned some of the supply with the burn function of the Interoperable Item Interface (ERC20 face of the Item). Recall that an Item has two faces, allowing it to work simultaneously as an ERC1155 (using its Main Interface) and as an ERC20 (using its Interoperable Interface).

Last updated