ERC1155.sol 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)
  3. pragma solidity ^0.8.0;
  4. import "./IERC1155.sol";
  5. import "./IERC1155Receiver.sol";
  6. import "./extensions/IERC1155MetadataURI.sol";
  7. import "../../utils/Address.sol";
  8. import "../../utils/Context.sol";
  9. import "../../utils/introspection/ERC165.sol";
  10. /**
  11. * @dev Implementation of the basic standard multi-token.
  12. * See https://eips.ethereum.org/EIPS/eip-1155
  13. * Originally based on code by Enjin: https://github.com/enjin/erc-1155
  14. *
  15. * _Available since v3.1._
  16. */
  17. contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
  18. using Address for address;
  19. // Mapping from token ID to account balances
  20. mapping(uint256 => mapping(address => uint256)) private _balances;
  21. // Mapping from account to operator approvals
  22. mapping(address => mapping(address => bool)) private _operatorApprovals;
  23. // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
  24. string private _uri;
  25. /**
  26. * @dev See {_setURI}.
  27. */
  28. constructor(string memory uri_) {
  29. _setURI(uri_);
  30. }
  31. /**
  32. * @dev See {IERC165-supportsInterface}.
  33. */
  34. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
  35. return
  36. interfaceId == type(IERC1155).interfaceId ||
  37. interfaceId == type(IERC1155MetadataURI).interfaceId ||
  38. super.supportsInterface(interfaceId);
  39. }
  40. /**
  41. * @dev See {IERC1155MetadataURI-uri}.
  42. *
  43. * This implementation returns the same URI for *all* token types. It relies
  44. * on the token type ID substitution mechanism
  45. * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
  46. *
  47. * Clients calling this function must replace the `\{id\}` substring with the
  48. * actual token type ID.
  49. */
  50. function uri(uint256) public view virtual override returns (string memory) {
  51. return _uri;
  52. }
  53. /**
  54. * @dev See {IERC1155-balanceOf}.
  55. *
  56. * Requirements:
  57. *
  58. * - `account` cannot be the zero address.
  59. */
  60. function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
  61. require(account != address(0), "ERC1155: address zero is not a valid owner");
  62. return _balances[id][account];
  63. }
  64. /**
  65. * @dev See {IERC1155-balanceOfBatch}.
  66. *
  67. * Requirements:
  68. *
  69. * - `accounts` and `ids` must have the same length.
  70. */
  71. function balanceOfBatch(
  72. address[] memory accounts,
  73. uint256[] memory ids
  74. ) public view virtual override returns (uint256[] memory) {
  75. require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
  76. uint256[] memory batchBalances = new uint256[](accounts.length);
  77. for (uint256 i = 0; i < accounts.length; ++i) {
  78. batchBalances[i] = balanceOf(accounts[i], ids[i]);
  79. }
  80. return batchBalances;
  81. }
  82. /**
  83. * @dev See {IERC1155-setApprovalForAll}.
  84. */
  85. function setApprovalForAll(address operator, bool approved) public virtual override {
  86. _setApprovalForAll(_msgSender(), operator, approved);
  87. }
  88. /**
  89. * @dev See {IERC1155-isApprovedForAll}.
  90. */
  91. function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
  92. return _operatorApprovals[account][operator];
  93. }
  94. /**
  95. * @dev See {IERC1155-safeTransferFrom}.
  96. */
  97. function safeTransferFrom(
  98. address from,
  99. address to,
  100. uint256 id,
  101. uint256 amount,
  102. bytes memory data
  103. ) public virtual override {
  104. require(
  105. from == _msgSender() || isApprovedForAll(from, _msgSender()),
  106. "ERC1155: caller is not token owner or approved"
  107. );
  108. _safeTransferFrom(from, to, id, amount, data);
  109. }
  110. /**
  111. * @dev See {IERC1155-safeBatchTransferFrom}.
  112. */
  113. function safeBatchTransferFrom(
  114. address from,
  115. address to,
  116. uint256[] memory ids,
  117. uint256[] memory amounts,
  118. bytes memory data
  119. ) public virtual override {
  120. require(
  121. from == _msgSender() || isApprovedForAll(from, _msgSender()),
  122. "ERC1155: caller is not token owner or approved"
  123. );
  124. _safeBatchTransferFrom(from, to, ids, amounts, data);
  125. }
  126. /**
  127. * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address.
  128. *
  129. * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.
  130. *
  131. * Requirements:
  132. *
  133. * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received}
  134. * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value.
  135. */
  136. function _update(
  137. address from,
  138. address to,
  139. uint256[] memory ids,
  140. uint256[] memory amounts,
  141. bytes memory data
  142. ) internal virtual {
  143. require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
  144. address operator = _msgSender();
  145. for (uint256 i = 0; i < ids.length; ++i) {
  146. uint256 id = ids[i];
  147. uint256 amount = amounts[i];
  148. if (from != address(0)) {
  149. uint256 fromBalance = _balances[id][from];
  150. require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
  151. unchecked {
  152. _balances[id][from] = fromBalance - amount;
  153. }
  154. }
  155. if (to != address(0)) {
  156. _balances[id][to] += amount;
  157. }
  158. }
  159. if (ids.length == 1) {
  160. uint256 id = ids[0];
  161. uint256 amount = amounts[0];
  162. emit TransferSingle(operator, from, to, id, amount);
  163. if (to != address(0)) {
  164. _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
  165. }
  166. } else {
  167. emit TransferBatch(operator, from, to, ids, amounts);
  168. if (to != address(0)) {
  169. _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
  170. }
  171. }
  172. }
  173. /**
  174. * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
  175. *
  176. * Emits a {TransferSingle} event.
  177. *
  178. * Requirements:
  179. *
  180. * - `to` cannot be the zero address.
  181. * - `from` must have a balance of tokens of type `id` of at least `amount`.
  182. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
  183. * acceptance magic value.
  184. */
  185. function _safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) internal {
  186. require(to != address(0), "ERC1155: transfer to the zero address");
  187. require(from != address(0), "ERC1155: transfer from the zero address");
  188. uint256[] memory ids = _asSingletonArray(id);
  189. uint256[] memory amounts = _asSingletonArray(amount);
  190. _update(from, to, ids, amounts, data);
  191. }
  192. /**
  193. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
  194. *
  195. * Emits a {TransferBatch} event.
  196. *
  197. * Requirements:
  198. *
  199. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
  200. * acceptance magic value.
  201. */
  202. function _safeBatchTransferFrom(
  203. address from,
  204. address to,
  205. uint256[] memory ids,
  206. uint256[] memory amounts,
  207. bytes memory data
  208. ) internal {
  209. require(to != address(0), "ERC1155: transfer to the zero address");
  210. require(from != address(0), "ERC1155: transfer from the zero address");
  211. _update(from, to, ids, amounts, data);
  212. }
  213. /**
  214. * @dev Sets a new URI for all token types, by relying on the token type ID
  215. * substitution mechanism
  216. * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
  217. *
  218. * By this mechanism, any occurrence of the `\{id\}` substring in either the
  219. * URI or any of the amounts in the JSON file at said URI will be replaced by
  220. * clients with the token type ID.
  221. *
  222. * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
  223. * interpreted by clients as
  224. * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
  225. * for token type ID 0x4cce0.
  226. *
  227. * See {uri}.
  228. *
  229. * Because these URIs cannot be meaningfully represented by the {URI} event,
  230. * this function emits no events.
  231. */
  232. function _setURI(string memory newuri) internal virtual {
  233. _uri = newuri;
  234. }
  235. /**
  236. * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
  237. *
  238. * Emits a {TransferSingle} event.
  239. *
  240. * Requirements:
  241. *
  242. * - `to` cannot be the zero address.
  243. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
  244. * acceptance magic value.
  245. */
  246. function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal {
  247. require(to != address(0), "ERC1155: mint to the zero address");
  248. uint256[] memory ids = _asSingletonArray(id);
  249. uint256[] memory amounts = _asSingletonArray(amount);
  250. _update(address(0), to, ids, amounts, data);
  251. }
  252. /**
  253. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
  254. *
  255. * Emits a {TransferBatch} event.
  256. *
  257. * Requirements:
  258. *
  259. * - `ids` and `amounts` must have the same length.
  260. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
  261. * acceptance magic value.
  262. */
  263. function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal {
  264. require(to != address(0), "ERC1155: mint to the zero address");
  265. _update(address(0), to, ids, amounts, data);
  266. }
  267. /**
  268. * @dev Destroys `amount` tokens of token type `id` from `from`
  269. *
  270. * Emits a {TransferSingle} event.
  271. *
  272. * Requirements:
  273. *
  274. * - `from` cannot be the zero address.
  275. * - `from` must have at least `amount` tokens of token type `id`.
  276. */
  277. function _burn(address from, uint256 id, uint256 amount) internal {
  278. require(from != address(0), "ERC1155: burn from the zero address");
  279. uint256[] memory ids = _asSingletonArray(id);
  280. uint256[] memory amounts = _asSingletonArray(amount);
  281. _update(from, address(0), ids, amounts, "");
  282. }
  283. /**
  284. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
  285. *
  286. * Emits a {TransferBatch} event.
  287. *
  288. * Requirements:
  289. *
  290. * - `ids` and `amounts` must have the same length.
  291. */
  292. function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal {
  293. require(from != address(0), "ERC1155: burn from the zero address");
  294. _update(from, address(0), ids, amounts, "");
  295. }
  296. /**
  297. * @dev Approve `operator` to operate on all of `owner` tokens
  298. *
  299. * Emits an {ApprovalForAll} event.
  300. */
  301. function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
  302. require(owner != operator, "ERC1155: setting approval status for self");
  303. _operatorApprovals[owner][operator] = approved;
  304. emit ApprovalForAll(owner, operator, approved);
  305. }
  306. function _doSafeTransferAcceptanceCheck(
  307. address operator,
  308. address from,
  309. address to,
  310. uint256 id,
  311. uint256 amount,
  312. bytes memory data
  313. ) private {
  314. if (to.isContract()) {
  315. try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
  316. if (response != IERC1155Receiver.onERC1155Received.selector) {
  317. revert("ERC1155: ERC1155Receiver rejected tokens");
  318. }
  319. } catch Error(string memory reason) {
  320. revert(reason);
  321. } catch {
  322. revert("ERC1155: transfer to non-ERC1155Receiver implementer");
  323. }
  324. }
  325. }
  326. function _doSafeBatchTransferAcceptanceCheck(
  327. address operator,
  328. address from,
  329. address to,
  330. uint256[] memory ids,
  331. uint256[] memory amounts,
  332. bytes memory data
  333. ) private {
  334. if (to.isContract()) {
  335. try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
  336. bytes4 response
  337. ) {
  338. if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
  339. revert("ERC1155: ERC1155Receiver rejected tokens");
  340. }
  341. } catch Error(string memory reason) {
  342. revert(reason);
  343. } catch {
  344. revert("ERC1155: transfer to non-ERC1155Receiver implementer");
  345. }
  346. }
  347. }
  348. function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
  349. uint256[] memory array = new uint256[](1);
  350. array[0] = element;
  351. return array;
  352. }
  353. }