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

ERC1412: Batch Transfers For Non-Fungible Tokens #1412

Open
mudgen opened this Issue Sep 15, 2018 · 7 comments

Comments

Projects
None yet
5 participants
@mudgen
Copy link
Contributor

mudgen commented Sep 15, 2018


eip: 1412
title: Batch Transfers For Non-Fungible Tokens
author: Nick Mudge nick@mokens.io
status: Draft
type: Standards Track
category: ERC
created: 2018-09-15
requires: ERC721


Simple Summary

An extension of the ERC721 standard that provides batch transfer functions.

Abstract

Adds batch transfer functions for ERC721 non-fungible tokens.

Motivation

Transferring multiple ERC721 tokens requires multiple transactions, which is inconvenient and uses more gas than necessary.

This standard solves this without replacing the ERC721 standard.

In some cases the gas savings that is possible with batch transfers is huge.

Specification

pragma solidity ^0.4.24;

/// @title ERC1412 Batch Transfers For Non-Fungible Tokens
///  Note: the ERC-165 identifier for this interface is 0x2b89bcaa
interface ERC1412 {
  /// @notice Transfers the ownership of multiple NFTs from one address to another address
  /// @param _from The current owner of the NFT
  /// @param _to The new owner
  /// @param _tokenIds The NFTs to transfer
  /// @param _data Additional data with no specified format, sent in call to `_to`  
  function safeBatchTransferFrom(address _from, address _to, uint256[] _tokenIds, bytes _data) external payable;
  
  /// @notice Transfers the ownership of multiple NFTs from one address to another address
  /// @param _from The current owner of the NFT
  /// @param _to The new owner
  /// @param _tokenIds The NFTs to transfer  
  function safeBatchTransferFrom(address _from, address _to, uint256[] _tokenIds) external payable; 

safeBatchTransferFrom(address _from, address _to, uint256[] _tokenIds, bytes _data) must implement the same functionality as safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) from the ERC721 standard but for multiple NFTs.

safeBatchTransferFrom(address _from, address _to, uint256[] _tokenIds) must implement the same functionality as safeTransferFrom(address _from, address _to, uint256 _tokenId) from the ERC721 standard but for multiple NFTs.

Rationale

This standard solves the problem of needing or wanting batch transfers without replacing the ERC721 standard which is widely adopted.

You will notice that there is no batchApprove function in this standard. The reason is because ERC721 already provides the setApprovalForAll function which is a form of batch approve and suffices.

A non-safe/unsafe batch transfer function is not needed.

Backwards Compatibility

This standard is compatible with the ERC721 standard.

Implementing this standard does not prevent third-party contracts from making batch transfers.

Copyright

Copyright and related rights waived via CC0.

@mudgen mudgen changed the title Batch Transfers For Non-Fungible Tokens ERC1412 Batch Transfers For Non-Fungible Tokens Sep 15, 2018

@mudgen mudgen changed the title ERC1412 Batch Transfers For Non-Fungible Tokens ERC1412: Batch Transfers For Non-Fungible Tokens Sep 15, 2018

@AusIV

This comment has been minimized.

Copy link

AusIV commented Sep 15, 2018

Does this really need to be a part of the token contract itself? It's already possible to batch token transfers via contracts that are approved operators, and those would be usable with ERC721 tokens that predate this standard. Additionally, separate contracts could potentially batch tokens from multiple ERC721 contracts in a single transaction.

This might be able to save a little bit of gas over using a separate contract, but it doesn't seem significant enough to justify complicating the token contract when it can be done almost as efficiently on a separate contract.

@mudgen

This comment has been minimized.

Copy link
Contributor

mudgen commented Sep 16, 2018

@AusIV Thank you for taking a look at this standard and considering it.

It does not need to be a part of the token contract itself. Contract programmers are free to implement this standard or not. Implementing this standard does not prevent third-party contracts from doing batch transfers. Someone could implement this standard and still have third-party contracts do batch transfers.

Implementing batch transfers in the token contract just solves certain problems and makes some things easier/better and saves gas.

I do not claim that this standard is appropriate for all NFT contracts, just that I think it is appropriate for enough to be useful.

If you don't want batch transfer functions complicating your NFT contract then they will complicate your third-party contract or wherever they end up. I don't know what complication you are thinking about. The complication depends on your contract and contract design. For some contracts and contract designs the complexity of adding 2 batch transfer functions is minimal and not an issue.

Here are problems solved by having batch transfers in the token contract:

  1. Third-party contracts that do batch transfers may not be known or easy to find because they aren't in the token contract. And third-party contracts that do batch transfers might be specific to some application and so may not be usable generally.
  2. Users who do not have a third-party contract are forced to make one, or find one, or transfer their tokens one by one which is horrible if they have a lot.

Here are things that are made better:

  1. A third-party contract requires a transaction that calls the setApprovalForAll before it can execute another transaction that does the batch transfer. If the batch transfer functions are in the NFT contract then users can call them directly without having to have a setApprovalForAll transaction. This reduces the number of transactions from 2 to 1. This isn't a big deal but is better.
  2. If the batch transfer functions are in the token contract then users only need to trust 1 contract when making a batch transfer. If a third-party contract is doing the transfer then the users have to trust 2 contracts. This is not a big deal either but it is better to trust less contracts.

Gas savings of batch transfer functions implemented in an NFT contract:

  1. Calling the function transferFrom(address _from, address _to, uint256 _tokenId) function in a third-party contract that does batch transfers costs about 2000 gas. You are right, if you aren't transferring many tokens and not often then the gas savings is minimal. But if you are transferring a ton of tokens or doing batch transfers frequently then the gas savings will be more.
@fulldecent

This comment has been minimized.

Copy link
Contributor

fulldecent commented Sep 16, 2018

I am still not satisfied with the quality of data being presented to argue that this approach will save (a meaningful amount of) gas.


Quick math:

SSTORE = 20,000 gas or 5,000 gas or
GASLIMIT = 8,000,000 gas

Gas used to transfer one token = TX overhead + permission check + actual transfer


I would like to see concretely the gas costs of using multiple transfers versus the proposed batch function.

@MoMannn

This comment has been minimized.

Copy link

MoMannn commented Sep 17, 2018

This proposal does batch transfers only from A to B. This could be enhanced to do batch transfers from A to n. Either by _to being an array of equal size then tokenIds or using structs as an input parameter(ABIEncoderV2).

@AusIV

This comment has been minimized.

Copy link

AusIV commented Sep 17, 2018

@MoMannn - If _to becomes an array, you're paying and additional 1360 gas per transferred item to designate its recipient (68 gas per byte of input data, times 20 bytes per address). That's fine if you want to send to a bunch of different recipients, but eats away at about 70% of the gas savings of this EIP if you want to send a bunch of items to the same recipient.

This brings me back to my point about just delegating batch transfers to another contract. What people want to get out of batch transfers isn't going to be consistent, and there are going to be tradeoffs of each approach. Trying to bake all of those possibilities into the token contract is going to create a lot of complexity and room for error, just to save a bit of gas on something that could already be handled pretty efficiently through purpose built contracts.

If the argument is that those contracts don't exist, go build them.

@MoMannn

This comment has been minimized.

Copy link

MoMannn commented Sep 17, 2018

@AusIV My argument is that if we are talking about standardizing batch transfers we should think more broadly then just transfer a to b. Plus I don't think that gas cost should be the driving force for standardization.

Otherwise I agree that delegation of batch transfers to another contract Is sufficient.

@dpdanpittman

This comment has been minimized.

Copy link

dpdanpittman commented Oct 17, 2018

Not sure if this needs to be a standard but its a good add on in my opinion. I need this function for my contract.

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