From 440b65bf776f57cba7a1562caabd94ce41dfb12a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 19 Apr 2021 22:13:15 +0200 Subject: [PATCH] Refactor ERC1155 transfers to use internal functions (#2636) * Refactor ERC1155 transfers to use internal functions #2622 * apply length check to all internal calls Co-authored-by: Robert Kaiser --- contracts/token/ERC1155/ERC1155.sol | 80 +++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/contracts/token/ERC1155/ERC1155.sol b/contracts/token/ERC1155/ERC1155.sol index ed2d8056f..cadc7ebb8 100644 --- a/contracts/token/ERC1155/ERC1155.sol +++ b/contracts/token/ERC1155/ERC1155.sol @@ -130,24 +130,11 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { virtual override { - require(to != address(0), "ERC1155: transfer to the zero address"); require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); - - uint256 fromBalance = _balances[id][from]; - require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); - _balances[id][from] = fromBalance - amount; - _balances[id][to] += amount; - - emit TransferSingle(operator, from, to, id, amount); - - _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); + _safeTransferFrom(from, to, id, amount, data); } /** @@ -164,12 +151,73 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { virtual override { - require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); - require(to != address(0), "ERC1155: transfer to the zero address"); require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); + _safeBatchTransferFrom(from, to, ids, amounts, data); + } + + /** + * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function _safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) + internal + virtual + { + require(to != address(0), "ERC1155: transfer to the zero address"); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); + + uint256 fromBalance = _balances[id][from]; + require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); + _balances[id][from] = fromBalance - amount; + _balances[id][to] += amount; + + emit TransferSingle(operator, from, to, id, amount); + + _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. + * + * Emits a {TransferBatch} event. + * + * Requirements: + * + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + */ + function _safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + internal + virtual + { + require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); + require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender();