ERC1155Upgradeable.sol 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts v4.4.1 (token/ERC1155/ERC1155.sol)
  3. pragma solidity ^0.8.0;
  4. import "./IERC1155Upgradeable.sol";
  5. import "./IERC1155ReceiverUpgradeable.sol";
  6. import "./extensions/IERC1155MetadataURIUpgradeable.sol";
  7. import "../../utils/AddressUpgradeable.sol";
  8. import "../../utils/ContextUpgradeable.sol";
  9. import "../../utils/introspection/ERC165Upgradeable.sol";
  10. import "../../proxy/utils/Initializable.sol";
  11. /**
  12. * @dev Implementation of the basic standard multi-token.
  13. * See https://eips.ethereum.org/EIPS/eip-1155
  14. * Originally based on code by Enjin: https://github.com/enjin/erc-1155
  15. *
  16. * _Available since v3.1._
  17. */
  18. contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
  19. using AddressUpgradeable for address;
  20. // Mapping from token ID to account balances
  21. mapping(uint256 => mapping(address => uint256)) private _balances;
  22. // Mapping from account to operator approvals
  23. mapping(address => mapping(address => bool)) private _operatorApprovals;
  24. // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
  25. string private _uri;
  26. /**
  27. * @dev See {_setURI}.
  28. */
  29. function __ERC1155_init(string memory uri_) internal onlyInitializing {
  30. __ERC1155_init_unchained(uri_);
  31. }
  32. function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
  33. _setURI(uri_);
  34. }
  35. /**
  36. * @dev See {IERC165-supportsInterface}.
  37. */
  38. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
  39. return
  40. interfaceId == type(IERC1155Upgradeable).interfaceId ||
  41. interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId ||
  42. super.supportsInterface(interfaceId);
  43. }
  44. /**
  45. * @dev See {IERC1155MetadataURI-uri}.
  46. *
  47. * This implementation returns the same URI for *all* token types. It relies
  48. * on the token type ID substitution mechanism
  49. * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
  50. *
  51. * Clients calling this function must replace the `\{id\}` substring with the
  52. * actual token type ID.
  53. */
  54. function uri(uint256) public view virtual override returns (string memory) {
  55. return _uri;
  56. }
  57. /**
  58. * @dev See {IERC1155-balanceOf}.
  59. *
  60. * Requirements:
  61. *
  62. * - `account` cannot be the zero address.
  63. */
  64. function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
  65. require(account != address(0), "ERC1155: balance query for the zero address");
  66. return _balances[id][account];
  67. }
  68. /**
  69. * @dev See {IERC1155-balanceOfBatch}.
  70. *
  71. * Requirements:
  72. *
  73. * - `accounts` and `ids` must have the same length.
  74. */
  75. function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
  76. public
  77. view
  78. virtual
  79. override
  80. returns (uint256[] memory)
  81. {
  82. require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
  83. uint256[] memory batchBalances = new uint256[](accounts.length);
  84. for (uint256 i = 0; i < accounts.length; ++i) {
  85. batchBalances[i] = balanceOf(accounts[i], ids[i]);
  86. }
  87. return batchBalances;
  88. }
  89. /**
  90. * @dev See {IERC1155-setApprovalForAll}.
  91. */
  92. function setApprovalForAll(address operator, bool approved) public virtual override {
  93. _setApprovalForAll(_msgSender(), operator, approved);
  94. }
  95. /**
  96. * @dev See {IERC1155-isApprovedForAll}.
  97. */
  98. function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
  99. return _operatorApprovals[account][operator];
  100. }
  101. /**
  102. * @dev See {IERC1155-safeTransferFrom}.
  103. */
  104. function safeTransferFrom(
  105. address from,
  106. address to,
  107. uint256 id,
  108. uint256 amount,
  109. bytes memory data
  110. ) public virtual override {
  111. require(
  112. from == _msgSender() || isApprovedForAll(from, _msgSender()),
  113. "ERC1155: caller is not owner nor approved"
  114. );
  115. _safeTransferFrom(from, to, id, amount, data);
  116. }
  117. /**
  118. * @dev See {IERC1155-safeBatchTransferFrom}.
  119. */
  120. function safeBatchTransferFrom(
  121. address from,
  122. address to,
  123. uint256[] memory ids,
  124. uint256[] memory amounts,
  125. bytes memory data
  126. ) public virtual override {
  127. require(
  128. from == _msgSender() || isApprovedForAll(from, _msgSender()),
  129. "ERC1155: transfer caller is not owner nor approved"
  130. );
  131. _safeBatchTransferFrom(from, to, ids, amounts, data);
  132. }
  133. /**
  134. * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
  135. *
  136. * Emits a {TransferSingle} event.
  137. *
  138. * Requirements:
  139. *
  140. * - `to` cannot be the zero address.
  141. * - `from` must have a balance of tokens of type `id` of at least `amount`.
  142. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
  143. * acceptance magic value.
  144. */
  145. function _safeTransferFrom(
  146. address from,
  147. address to,
  148. uint256 id,
  149. uint256 amount,
  150. bytes memory data
  151. ) internal virtual {
  152. require(to != address(0), "ERC1155: transfer to the zero address");
  153. address operator = _msgSender();
  154. _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
  155. uint256 fromBalance = _balances[id][from];
  156. require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
  157. unchecked {
  158. _balances[id][from] = fromBalance - amount;
  159. }
  160. _balances[id][to] += amount;
  161. emit TransferSingle(operator, from, to, id, amount);
  162. _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
  163. }
  164. /**
  165. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
  166. *
  167. * Emits a {TransferBatch} event.
  168. *
  169. * Requirements:
  170. *
  171. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
  172. * acceptance magic value.
  173. */
  174. function _safeBatchTransferFrom(
  175. address from,
  176. address to,
  177. uint256[] memory ids,
  178. uint256[] memory amounts,
  179. bytes memory data
  180. ) internal virtual {
  181. require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
  182. require(to != address(0), "ERC1155: transfer to the zero address");
  183. address operator = _msgSender();
  184. _beforeTokenTransfer(operator, from, to, ids, amounts, data);
  185. for (uint256 i = 0; i < ids.length; ++i) {
  186. uint256 id = ids[i];
  187. uint256 amount = amounts[i];
  188. uint256 fromBalance = _balances[id][from];
  189. require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
  190. unchecked {
  191. _balances[id][from] = fromBalance - amount;
  192. }
  193. _balances[id][to] += amount;
  194. }
  195. emit TransferBatch(operator, from, to, ids, amounts);
  196. _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
  197. }
  198. /**
  199. * @dev Sets a new URI for all token types, by relying on the token type ID
  200. * substitution mechanism
  201. * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
  202. *
  203. * By this mechanism, any occurrence of the `\{id\}` substring in either the
  204. * URI or any of the amounts in the JSON file at said URI will be replaced by
  205. * clients with the token type ID.
  206. *
  207. * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
  208. * interpreted by clients as
  209. * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
  210. * for token type ID 0x4cce0.
  211. *
  212. * See {uri}.
  213. *
  214. * Because these URIs cannot be meaningfully represented by the {URI} event,
  215. * this function emits no events.
  216. */
  217. function _setURI(string memory newuri) internal virtual {
  218. _uri = newuri;
  219. }
  220. /**
  221. * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
  222. *
  223. * Emits a {TransferSingle} event.
  224. *
  225. * Requirements:
  226. *
  227. * - `to` cannot be the zero address.
  228. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
  229. * acceptance magic value.
  230. */
  231. function _mint(
  232. address to,
  233. uint256 id,
  234. uint256 amount,
  235. bytes memory data
  236. ) internal virtual {
  237. require(to != address(0), "ERC1155: mint to the zero address");
  238. address operator = _msgSender();
  239. _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data);
  240. _balances[id][to] += amount;
  241. emit TransferSingle(operator, address(0), to, id, amount);
  242. _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
  243. }
  244. /**
  245. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
  246. *
  247. * Requirements:
  248. *
  249. * - `ids` and `amounts` must have the same length.
  250. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
  251. * acceptance magic value.
  252. */
  253. function _mintBatch(
  254. address to,
  255. uint256[] memory ids,
  256. uint256[] memory amounts,
  257. bytes memory data
  258. ) internal virtual {
  259. require(to != address(0), "ERC1155: mint to the zero address");
  260. require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
  261. address operator = _msgSender();
  262. _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
  263. for (uint256 i = 0; i < ids.length; i++) {
  264. _balances[ids[i]][to] += amounts[i];
  265. }
  266. emit TransferBatch(operator, address(0), to, ids, amounts);
  267. _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
  268. }
  269. /**
  270. * @dev Destroys `amount` tokens of token type `id` from `from`
  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(
  278. address from,
  279. uint256 id,
  280. uint256 amount
  281. ) internal virtual {
  282. require(from != address(0), "ERC1155: burn from the zero address");
  283. address operator = _msgSender();
  284. _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
  285. uint256 fromBalance = _balances[id][from];
  286. require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
  287. unchecked {
  288. _balances[id][from] = fromBalance - amount;
  289. }
  290. emit TransferSingle(operator, from, address(0), id, amount);
  291. }
  292. /**
  293. * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
  294. *
  295. * Requirements:
  296. *
  297. * - `ids` and `amounts` must have the same length.
  298. */
  299. function _burnBatch(
  300. address from,
  301. uint256[] memory ids,
  302. uint256[] memory amounts
  303. ) internal virtual {
  304. require(from != address(0), "ERC1155: burn from the zero address");
  305. require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
  306. address operator = _msgSender();
  307. _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
  308. for (uint256 i = 0; i < ids.length; i++) {
  309. uint256 id = ids[i];
  310. uint256 amount = amounts[i];
  311. uint256 fromBalance = _balances[id][from];
  312. require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
  313. unchecked {
  314. _balances[id][from] = fromBalance - amount;
  315. }
  316. }
  317. emit TransferBatch(operator, from, address(0), ids, amounts);
  318. }
  319. /**
  320. * @dev Approve `operator` to operate on all of `owner` tokens
  321. *
  322. * Emits a {ApprovalForAll} event.
  323. */
  324. function _setApprovalForAll(
  325. address owner,
  326. address operator,
  327. bool approved
  328. ) internal virtual {
  329. require(owner != operator, "ERC1155: setting approval status for self");
  330. _operatorApprovals[owner][operator] = approved;
  331. emit ApprovalForAll(owner, operator, approved);
  332. }
  333. /**
  334. * @dev Hook that is called before any token transfer. This includes minting
  335. * and burning, as well as batched variants.
  336. *
  337. * The same hook is called on both single and batched variants. For single
  338. * transfers, the length of the `id` and `amount` arrays will be 1.
  339. *
  340. * Calling conditions (for each `id` and `amount` pair):
  341. *
  342. * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
  343. * of token type `id` will be transferred to `to`.
  344. * - When `from` is zero, `amount` tokens of token type `id` will be minted
  345. * for `to`.
  346. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
  347. * will be burned.
  348. * - `from` and `to` are never both zero.
  349. * - `ids` and `amounts` have the same, non-zero length.
  350. *
  351. * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
  352. */
  353. function _beforeTokenTransfer(
  354. address operator,
  355. address from,
  356. address to,
  357. uint256[] memory ids,
  358. uint256[] memory amounts,
  359. bytes memory data
  360. ) internal virtual {}
  361. function _doSafeTransferAcceptanceCheck(
  362. address operator,
  363. address from,
  364. address to,
  365. uint256 id,
  366. uint256 amount,
  367. bytes memory data
  368. ) private {
  369. if (to.isContract()) {
  370. try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
  371. if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) {
  372. revert("ERC1155: ERC1155Receiver rejected tokens");
  373. }
  374. } catch Error(string memory reason) {
  375. revert(reason);
  376. } catch {
  377. revert("ERC1155: transfer to non ERC1155Receiver implementer");
  378. }
  379. }
  380. }
  381. function _doSafeBatchTransferAcceptanceCheck(
  382. address operator,
  383. address from,
  384. address to,
  385. uint256[] memory ids,
  386. uint256[] memory amounts,
  387. bytes memory data
  388. ) private {
  389. if (to.isContract()) {
  390. try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
  391. bytes4 response
  392. ) {
  393. if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) {
  394. revert("ERC1155: ERC1155Receiver rejected tokens");
  395. }
  396. } catch Error(string memory reason) {
  397. revert(reason);
  398. } catch {
  399. revert("ERC1155: transfer to non ERC1155Receiver implementer");
  400. }
  401. }
  402. }
  403. function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
  404. uint256[] memory array = new uint256[](1);
  405. array[0] = element;
  406. return array;
  407. }
  408. /**
  409. * This empty reserved space is put in place to allow future versions to add new
  410. * variables without shifting down storage in the inheritance chain.
  411. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  412. */
  413. uint256[47] private __gap;
  414. }