New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ERC1155: MultiToken Standard #24

Open
dekz opened this Issue Nov 12, 2018 · 2 comments

Comments

Projects
None yet
3 participants
@dekz
Copy link
Member

dekz commented Nov 12, 2018

Summary

0x aims to provide support for token standards beyond ERC20 and ERC721. Provide support for the ERC1155 token standard when it has been finalised. This support would be in the form of an AssetProxy specifically for ERC1155.

Motivation

Many projects including gaming project require a more efficient token standard than what ERC721 can provide. This has been a commonly requested feature from a number of projects wishing to use 0x.

Specification

ERC115 has support for single transfer and batch transfer.

    /**
        @notice Transfers value amount of an _id from the _from address to the _to addresses specified. Each parameter array should be the same length, with each index correlating.
        @dev MUST emit Transfer event on success.
        Caller must have sufficient allowance by _from for the _id/_value pair, or isApprovedForAll must be true.
        Throws if `_to` is the zero address.
        Throws if `_id` is not a valid token ID.
        When transfer is complete, this function checks if `_to` is a smart contract (code size > 0). If so, it calls `onERC1155Received` on `_to` and throws if the return value is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
        @param _from    source addresses
        @param _to      target addresses
        @param _id      ID of the Token
        @param _value   transfer amounts
        @param _data    Additional data with no specified format, sent in call to `_to`
    */
    function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes _data) external;

    /**
        @notice Send multiple types of Tokens from a 3rd party in one transfer (with safety call)
        @dev MUST emit Transfer event per id on success.
        Caller must have a sufficient allowance by _from for each of the id/value pairs.
        Throws on any error rather than return a false flag to minimize user errors.
        @param _from    Source address
        @param _to      Target address
        @param _ids     Types of Tokens
        @param _values  Transfer amounts per token type
        @param _data    Additional data with no specified format, sent in call to `_to`
    */
    function safeBatchTransferFrom(address _from, address _to, uint256[] _ids, uint256[] _values, bytes _data) external;

Batch transfer is the primary efficiency of ERC1155 over ERC721. In the past we have favoured the simpler transferFrom without bytes _data to prevent any unknown state changes during the atomic swap.

We may favour not supporting the bytes _data parameter to avoid any state change when the user receives a callback and is in possession of both assets.

Supporting batch transfers as default would be the most likely candidate in terms of feature set of ERC1155.

// 0x6cedd4fb
ERC1155Token(uint256[] _ids, uint256[] _values)

This would result in additional gas costs for the single transfer use-case, so it may be wise to add support for both with an additional selector.

// 0x39c6aa3a
ERC1155Token(uint256 _id, uint256 _value)

Issues

  • Await finalisation of the standard to reduce the chance of wasted effort and reduce the chance of adoption of a draft standard
  • Decide on whether the user can specify the bytes _data field
  • Decide on supporting single transfer in addition to batch transfer
@redsquirrel

This comment has been minimized.

Copy link

redsquirrel commented Nov 12, 2018

ERC115 has support for single transfer and batch transfer.

ERC1155

@PhABC

This comment has been minimized.

Copy link
Contributor

PhABC commented Nov 19, 2018

I made this a few months ago to test 0x with 1155, might find it useful, although not optimized at all :

Click to see code
/*
  Copyright 2018 ZeroEx Intl.
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

/** 
* TO DO : 
*    + Add support for batchTransferFrom
*    + Add support for safeBatchTransferFrom
*    + Convert to assembly code
*/

pragma solidity 0.4.24;

import "../../utils/LibBytes/LibBytes.sol";
import "./MixinAuthorizable.sol";
import "multi-token-standard/contracts/token/IERC1155.sol";

contract ERC1155Proxy is MixinAuthorizable
{   
  using LibBytes for bytes;

  // assetData index constants
  uint256 constant internal TOKEN_ADDRESS_INDEX = 16; // To use with readAddress()
  uint256 constant internal TOKEN_ID_INDEX      = 36; // To use with readUint256()
  // uint8 constant internal TOKEN_AMOUNT_INDEX  = 0x68; // To use with readUint256()

  // Id of this proxy.
  bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Token(address,uint256)"));

  /// @dev Transfers assets. Either succeeds or throws.
  /// @param assetData Byte array encoded for the respective asset proxy.
  /// @param from Address to transfer asset from.
  /// @param to Address to transfer asset to.
  /// @param amount Amount of asset to transfer.
  function transferFrom(
    bytes assetData,
    address from,
    address to,
    uint256 amount
  )
    external
  {

      // Asset data itself is encoded as follows:
      //
      // | Area     | Offset | Length  | Contents                            |
      // |----------|--------|---------|-------------------------------------|
      // | Header   | 0      | 4       | Proxy ID                            |
      // | Params   |        | 2 * 32  | Function parameters:                |
      // |          | 4      | 12 + 20 |   1. Token address                  |
      // |          | 36     | 32      |   2. Token Id                       |
      // |          |        |         |                                     |

      // Token address
      address token = assetData.readAddress(TOKEN_ADDRESS_INDEX); 

      // Token Id
      uint256 tokenId = assetData.readUint256(TOKEN_ID_INDEX);

      // Transfer token in ERC155 contract
      IERC1155(token).safeTransferFrom(from, to, tokenId, amount, '');
  }    

  /// @dev Gets the proxy id associated with the proxy address.
  /// @return Proxy id.
  function getProxyId()
    external
    pure
    returns (bytes4)
  {
    return PROXY_ID;
  }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment