├── .gitattributes
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── migrations
├── 2_deploy_contracts.js
└── 1_initial_migration.js
├── src
├── components
│ ├── App.css
│ └── App.js
├── index.js
├── contracts
│ ├── Migrations.sol
│ ├── Memes.sol
│ └── ERC1155.sol
└── serviceWorker.js
├── .gitignore
├── truffle-config.js
├── README.md
├── package.json
└── test
└── Memes.test.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sol linguist-language=Solidity
2 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matprime/ERC-1155-NFT-demo/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | const Memes = artifacts.require("Memes");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Memes);
5 | };
6 |
--------------------------------------------------------------------------------
/src/components/App.css:
--------------------------------------------------------------------------------
1 | /* Styles go here */
2 |
3 | .token {
4 | height: 150px;
5 | width: 150px;
6 | border-radius: 50%;
7 | display: inline-block;
8 | }
9 |
--------------------------------------------------------------------------------
/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | const Migrations = artifacts.require("Migrations");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Demo Kit",
3 | "name": "NFT Starter Kit",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 | .env
21 | .secret
22 |
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # abis folder
28 | /src/abis
29 | */abis
30 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import 'bootstrap/dist/css/bootstrap.css'
4 | import App from './components/App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 |
9 | // If you want your app to work offline and load faster, you can change
10 | // unregister() to register() below. Note this comes with some pitfalls.
11 | // Learn more about service workers: https://bit.ly/CRA-PWA
12 | serviceWorker.unregister();
13 |
--------------------------------------------------------------------------------
/src/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.6.0;
2 |
3 | contract Migrations {
4 | address public owner;
5 | uint public last_completed_migration;
6 |
7 | constructor() public {
8 | owner = msg.sender;
9 | }
10 |
11 | modifier restricted() {
12 | if (msg.sender == owner) _;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/truffle-config.js:
--------------------------------------------------------------------------------
1 | require('babel-register');
2 | require('babel-polyfill');
3 | const HDWalletProvider = require('truffle-hdwallet-provider');
4 | const fs = require('fs');
5 | const mnemonic = fs.readFileSync(".secret").toString().trim();
6 | var networkId = process.env.npm_package_config_ganache_networkId;
7 | var gasPrice = process.env.npm_package_config_ganache_gasPrice;
8 | var gasLimit = process.env.npm_package_config_ganache_gasLimit;
9 |
10 | module.exports = {
11 | networks: {
12 | development: {
13 | host: "127.0.0.1",
14 | port: 8545,
15 | network_id: "*" // Match any network id
16 | },
17 | matic: {
18 | provider: () => new HDWalletProvider(mnemonic, `https://rpc-mumbai.matic.today`),
19 | network_id: 80001,
20 | confirmations: 2,
21 | timeoutBlocks: 200,
22 | skipDryRun: true
23 | },
24 | },
25 | contracts_directory: './src/contracts/',
26 | contracts_build_directory: './src/abis/',
27 | compilers: {
28 | solc: {
29 | version: "^0.6.0",
30 | optimizer: {
31 | enabled: true,
32 | runs: 200
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ERC-1155_NFT_creation_demo
2 | how to create NFT's using ERC1155, create different URIs for every NFT and pay out part of provision at NFT sale to third party
3 | ## Installation procedure
4 | ```shell
5 | git clone git clone https://github.com/matprime/ERC-1155-NFT-demo
6 | cd ERC-1155-NFT-demo
7 | npm install
8 | ```
9 | ## Compiling smart contract, deployment to blockchain and test
10 | ```shell
11 | truffle compile
12 | truffle migrate --reset
13 | truffle test
14 | ```
15 | Before deploying smart contracts to blockchain "truffle migrate --reset", you need to make sure that local Ethereum blockchain is running.
16 | Demo was tested with ganache-cli local blockchain, and Matic Mumbai testnet.
17 | To run tests on local Ethereum blockchain then first run ganache-cli with command "ganache-cli"
18 | and you will get 10 Ethereum test account filled with 100 test Ether to use for testing of demo.
19 | ## Starting demo
20 | ```shell
21 | npm run start
22 | ```
23 | Browser window will open and demo will be started. For use of demo you need to use Metamask wallet,
24 | configure it to work with local blockchain and import one of test accounts which ganache generated.
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nft-demo",
3 | "version": "0.1.0",
4 | "description": "demo how to create NFT's ERC-721 and work with their additional attribute",
5 | "author": "matt@mattprime.com",
6 | "dependencies": {
7 | "babel-polyfill": "6.26.0",
8 | "babel-preset-env": "1.7.0",
9 | "babel-preset-es2015": "6.24.1",
10 | "babel-preset-stage-2": "6.24.1",
11 | "babel-preset-stage-3": "6.24.1",
12 | "babel-register": "6.26.0",
13 | "bootstrap": "4.3.1",
14 | "chai": "4.2.0",
15 | "chai-as-promised": "7.1.1",
16 | "chai-bignumber": "3.0.0",
17 | "react": "16.8.4",
18 | "react-bootstrap": "1.0.0-beta.5",
19 | "react-dom": "16.8.4",
20 | "react-scripts": "2.1.3",
21 | "truffle": "^5.1.52",
22 | "truffle-flattener": "^1.5.0",
23 | "truffle-hdwallet-provider": "^1.0.17",
24 | "web3": "1.0.0-beta.55"
25 | },
26 | "scripts": {
27 | "start": "react-scripts start",
28 | "build": "react-scripts build",
29 | "test": "react-scripts test",
30 | "eject": "react-scripts eject"
31 | },
32 | "eslintConfig": {
33 | "extends": "react-app"
34 | },
35 | "browserslist": [
36 | ">0.2%",
37 | "not dead",
38 | "not ie <= 11",
39 | "not op_mini all"
40 | ],
41 | "devDependencies": {
42 | "@openzeppelin/contracts": "^2.5.1"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
25 | NFT ERC1155 demo
26 |
27 |
28 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/test/Memes.test.js:
--------------------------------------------------------------------------------
1 | const Web3 = require("web3")
2 | const Memes = artifacts.require('./Memes.sol')
3 |
4 | require('chai')
5 | .use(require('chai-as-promised'))
6 | .should()
7 |
8 | contract('Memes', (accounts) => {
9 | let contract
10 |
11 | before(async () => {
12 | contract = await Memes.deployed()
13 | })
14 |
15 | describe('deployment', async () => {
16 | it('deploys successfully', async () => {
17 | const address = contract.address
18 | assert.notEqual(address, 0x0)
19 | assert.notEqual(address, '')
20 | assert.notEqual(address, null)
21 | assert.notEqual(address, undefined)
22 | })
23 |
24 | })
25 |
26 | describe('minting', async () => {
27 | it('creates a new NFT token', async () => {
28 | const result = await contract.mint('ECEA058EF4523', 'uri0')
29 | const totalSupply = await contract.balanceOf(accounts[0], 0)
30 | // is only one NFT of this type created in this account
31 | assert.equal(totalSupply, 1)
32 | // check NFT id, from address, to address
33 | const event = result.logs[0].args
34 | assert.equal(event.id, 0, 'id is correct')
35 | assert.equal(event.from, '0x0000000000000000000000000000000000000000', 'from is correct')
36 | assert.equal(event.to, accounts[0], 'to is correct')
37 | // FAILURE: cannot mint same hash twice
38 | await contract.mint('ECEA058EF4523', 'uri1').should.be.rejected
39 | })
40 | })
41 |
42 | describe('indexing', async () => {
43 | it('lists hashes', async () => {
44 | // Mint 3 more NFT tokens
45 | await contract.mint('5386E4EABC345', 'uri1')
46 | await contract.mint('FFF567EAB5FFF', 'uri2')
47 | await contract.mint('234AEC00EFFD0', 'uri3')
48 |
49 | //check number of minted NFTs
50 | const memesCount = await contract.getMemesCount()
51 | assert.equal(memesCount, 4)
52 |
53 |
54 | let hash
55 | let result = []
56 | //check indexing and hashes of minted NFTs
57 | for (var i = 1; i <= memesCount; i++) {
58 | hash = await contract.hashes(i - 1)
59 | result.push(hash)
60 | }
61 |
62 | let expected = ['ECEA058EF4523', '5386E4EABC345', 'FFF567EAB5FFF', '234AEC00EFFD0']
63 | assert.equal(result.join(','), expected.join(','))
64 | })
65 | })
66 |
67 | describe('URIs', async () => {
68 | it('retrieves URIs', async () => {
69 | let result1 = await contract.uri(1)
70 | assert.equal(result1, 'uri1')
71 | let result2 = await contract.uri(2)
72 | assert.equal(result2, 'uri2')
73 | })
74 | it('change URI', async () => {
75 | await contract.setTokenUri(1, 'test1')
76 | let result3 = await contract.uri(1)
77 | assert.equal(result3, 'test1')
78 | })
79 | //only owner of smart contract is able to change the uri of NFT
80 | it('change URI onlyOwner', async () => {
81 | await contract.setTokenUri(2, 'test2', { from: accounts[1] }).should.be.rejected
82 | })
83 | })
84 |
85 | describe('transfering', async () => {
86 | it('transferring NFT', async () => {
87 | let result = await contract.safeTransferFrom(accounts[0], accounts[2], 0, 1, "0x0")
88 | const event = result.logs[0].args
89 | assert.equal(event.to, accounts[2])
90 | })
91 | })
92 |
93 | //describe('selling', async () => {
94 | // it('selling NFT with provision', async () => {
95 | //
96 | // let result = await contract.safeTransferFromWithProvision(accounts[0], accounts[2], 1, 1, web3.utils.toWei('100', 'Ether'))
97 | // const event = result.logs[0].args
98 | // assert.equal(event.to, accounts[3])
99 | // })
100 | //})
101 |
102 |
103 | })
104 |
--------------------------------------------------------------------------------
/src/contracts/Memes.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | import "./ERC1155.sol";
3 |
4 | pragma solidity >=0.6.0 <0.8.0;
5 |
6 | /**
7 | * @dev Contract module which provides a basic access control mechanism, where
8 | * there is an account (an owner) that can be granted exclusive access to
9 | * specific functions.
10 | *
11 | * By default, the owner account will be the one that deploys the contract. This
12 | * can later be changed with {transferOwnership}.
13 | *
14 | * This module is used through inheritance. It will make available the modifier
15 | * `onlyOwner`, which can be applied to your functions to restrict their use to
16 | * the owner.
17 | */
18 | abstract contract Ownable is Context {
19 | address private _owner;
20 |
21 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
22 |
23 | /**
24 | * @dev Initializes the contract setting the deployer as the initial owner.
25 | */
26 | constructor () internal {
27 | address msgSender = _msgSender();
28 | _owner = msgSender;
29 | emit OwnershipTransferred(address(0), msgSender);
30 | }
31 |
32 | /**
33 | * @dev Returns the address of the current owner.
34 | */
35 | function owner() public view returns (address) {
36 | return _owner;
37 | }
38 |
39 | /**
40 | * @dev Throws if called by any account other than the owner.
41 | */
42 | modifier onlyOwner() {
43 | require(_owner == _msgSender(), "Ownable: caller is not the owner");
44 | _;
45 | }
46 |
47 | /**
48 | * @dev Leaves the contract without owner. It will not be possible to call
49 | * `onlyOwner` functions anymore. Can only be called by the current owner.
50 | *
51 | * NOTE: Renouncing ownership will leave the contract without an owner,
52 | * thereby removing any functionality that is only available to the owner.
53 | */
54 | function renounceOwnership() public virtual onlyOwner {
55 | emit OwnershipTransferred(_owner, address(0));
56 | _owner = address(0);
57 | }
58 |
59 | /**
60 | * @dev Transfers ownership of the contract to a new account (`newOwner`).
61 | * Can only be called by the current owner.
62 | */
63 | function transferOwnership(address newOwner) public virtual onlyOwner {
64 | require(newOwner != address(0), "Ownable: new owner is the zero address");
65 | emit OwnershipTransferred(_owner, newOwner);
66 | _owner = newOwner;
67 | }
68 | }
69 |
70 |
71 | contract Memes is ERC1155, Ownable {
72 |
73 | // Hashes of meme pictures on IPFS
74 | string[] public hashes;
75 | // Mapping for enforcing unique hashes
76 | mapping(string => bool) _hashExists;
77 |
78 | // Mapping from NFT token ID to owner
79 | mapping (uint256 => address) private _tokenOwner;
80 |
81 | // Mapping from hash to NFT token ID
82 | mapping (string => address) private _hashToken;
83 |
84 | constructor() public ERC1155("https://game.example/api/item/{id}.json") {
85 | }
86 |
87 | function mint(string memory _hash, string memory _uri) public {
88 | require(!_hashExists[_hash], "Token is already minted");
89 | require(bytes(_uri).length > 0, "uri should be set");
90 | hashes.push(_hash);
91 | uint _id = hashes.length - 1;
92 | _mint(msg.sender, _id, 1, _uri, "");
93 | _hashExists[_hash] = true;
94 | }
95 |
96 | function getMemesCount() public view returns(uint256 count) {
97 | return hashes.length;
98 | }
99 |
100 | function uri(uint256 _tokenId) public view override returns(string memory _uri) {
101 | return _tokenURI(_tokenId);
102 | }
103 |
104 | function setTokenUri(uint256 _tokenId, string memory _uri) public onlyOwner {
105 | _setTokenURI(_tokenId, _uri);
106 | }
107 |
108 | function safeTransferFromWithProvision(
109 | address payable from,
110 | address to,
111 | uint256 id,
112 | uint256 amount,
113 | uint256 price
114 | )
115 | public payable returns(bool approved)
116 | {
117 | setApprovalForAll(to,true);
118 | safeTransferFrom(from, to, id, amount, "0x0");
119 | return isApprovedForAll(from, to);
120 | //from.transfer(price);
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Web3 from 'web3'
3 | import './App.css';
4 | import Meme from '../abis/Memes.json'
5 |
6 | class App extends Component {
7 |
8 | async componentWillMount() {
9 | await this.loadWeb3()
10 | await this.loadBlockchainData()
11 | }
12 |
13 | async loadWeb3() {
14 | if (window.ethereum) {
15 | window.web3 = new Web3(window.ethereum)
16 | await window.ethereum.enable()
17 | }
18 | else if (window.web3) {
19 | window.web3 = new Web3(window.web3.currentProvider)
20 | }
21 | else {
22 | window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
23 | }
24 | }
25 |
26 | async loadBlockchainData() {
27 | const web3 = window.web3
28 | // Load account
29 | const accounts = await web3.eth.getAccounts()
30 | this.setState({ account: accounts[0] })
31 |
32 | const networkId = await web3.eth.net.getId()
33 | const networkData = Meme.networks[networkId]
34 | if (networkData) {
35 | const abi = Meme.abi
36 | const address = networkData.address
37 | const contract = new web3.eth.Contract(abi, address)
38 | this.setState({ contract })
39 | const totalSupply = await contract.methods.getMemesCount().call()
40 | this.setState({ totalSupply })
41 | console.log('total supply')
42 | console.log(totalSupply)
43 | // Load hashes
44 | for (var i = 1; i <= totalSupply; i++) {
45 | const hash = await contract.methods.hashes(i - 1).call()
46 | console.log(hash)
47 | this.setState({
48 | hashes: [...this.state.hashes, hash]
49 | })
50 | }
51 | } else {
52 | window.alert('Smart contract not deployed to detected network.')
53 | }
54 | }
55 |
56 | mint = (hash, uri) => {
57 | this.state.contract.methods.mint(hash,uri).send({ from: this.state.account })
58 | .once('receipt', (receipt) => {
59 | this.setState({
60 | hashes: [...this.state.hashes, hash],
61 | uris: [...this.state.hashes, uri]
62 | })
63 | })
64 |
65 | console.log("mint is done")
66 | //const tokenURI = this.state.contract.methods.getTokenUri().call()
67 | //.then(function(resp) {
68 | // console.log(resp)
69 | //})
70 | //console.log("tokenURI = " + tokenURI)
71 |
72 | }
73 |
74 | buy = (hash) => {
75 | const web3 = window.web3
76 | this.state.contract.methods.safeTransferFromWithProvision(
77 | '0x6605f1b2A3482242DDE3B2D3fbAE8b7384D631EE',
78 | '0x52745cD8E7F2E2D073B7c3F76a565eB6CF700BBB',
79 | 1,
80 | 1,
81 | web3.utils.toWei('1' , 'wei'))
82 | .call()
83 | .then(function(resp) {
84 | console.log(resp)
85 | })
86 | console.log('from: ' + '0x6605f1b2A3482242DDE3B2D3fbAE8b7384D631EE')
87 | console.log('to: ' + '0x52745cD8E7F2E2D073B7c3F76a565eB6CF700BBB')
88 | console.log("buy of NFT with hash: " + hash + " is done")
89 | }
90 |
91 | constructor(props) {
92 | super(props)
93 | this.state = {
94 | account: '',
95 | contract: null,
96 | totalSupply: 0,
97 | hashes: [],
98 | uris: [],
99 | owner: '0x8B190f0BcC72aB322eF9209030B4358eE71220E0'
100 | }
101 | }
102 |
103 | render() {
104 | return (
105 |
106 |
121 |
122 |
123 |
124 |
125 |
Issue NFT Token
126 |
143 |
144 |
145 |
146 |
147 |
148 | { this.state.hashes.map((hash, key) => {
149 | return(
150 |
151 |
{hash}
152 |
156 |
157 | )
158 | })}
159 |
160 |
161 |
162 | );
163 | }
164 | }
165 |
166 | export default App;
167 |
--------------------------------------------------------------------------------
/src/contracts/ERC1155.sol:
--------------------------------------------------------------------------------
1 | // File: openzeppelin-contracts-master/contracts/introspection/IERC165.sol
2 |
3 | // SPDX-License-Identifier: MIT
4 |
5 | pragma solidity ^0.6.0;
6 |
7 | /**
8 | * @dev Interface of the ERC165 standard, as defined in the
9 | * https://eips.ethereum.org/EIPS/eip-165[EIP].
10 | *
11 | * Implementers can declare support of contract interfaces, which can then be
12 | * queried by others ({ERC165Checker}).
13 | *
14 | * For an implementation, see {ERC165}.
15 | */
16 | interface IERC165 {
17 | /**
18 | * @dev Returns true if this contract implements the interface defined by
19 | * `interfaceId`. See the corresponding
20 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
21 | * to learn more about how these ids are created.
22 | *
23 | * This function call must use less than 30 000 gas.
24 | */
25 | function supportsInterface(bytes4 interfaceId) external view returns (bool);
26 | }
27 |
28 | // File: openzeppelin-contracts-master/contracts/token/ERC1155/IERC1155.sol
29 |
30 | pragma solidity ^0.6.2;
31 |
32 |
33 | /**
34 | * @dev Required interface of an ERC1155 compliant contract, as defined in the
35 | * https://eips.ethereum.org/EIPS/eip-1155[EIP].
36 | *
37 | * _Available since v3.1._
38 | */
39 | interface IERC1155 is IERC165 {
40 | /**
41 | * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
42 | */
43 | event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
44 |
45 | /**
46 | * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
47 | * transfers.
48 | */
49 | event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
50 |
51 | /**
52 | * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
53 | * `approved`.
54 | */
55 | event ApprovalForAll(address indexed account, address indexed operator, bool approved);
56 |
57 | /**
58 | * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
59 | *
60 | * If an {URI} event was emitted for `id`, the standard
61 | * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
62 | * returned by {IERC1155MetadataURI-uri}.
63 | */
64 | event URI(string value, uint256 indexed id);
65 |
66 | /**
67 | * @dev Returns the amount of tokens of token type `id` owned by `account`.
68 | *
69 | * Requirements:
70 | *
71 | * - `account` cannot be the zero address.
72 | */
73 | function balanceOf(address account, uint256 id) external view returns (uint256);
74 |
75 | /**
76 | * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
77 | *
78 | * Requirements:
79 | *
80 | * - `accounts` and `ids` must have the same length.
81 | */
82 | function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
83 |
84 | /**
85 | * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
86 | *
87 | * Emits an {ApprovalForAll} event.
88 | *
89 | * Requirements:
90 | *
91 | * - `operator` cannot be the caller.
92 | */
93 | function setApprovalForAll(address operator, bool approved) external;
94 |
95 | /**
96 | * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
97 | *
98 | * See {setApprovalForAll}.
99 | */
100 | function isApprovedForAll(address account, address operator) external view returns (bool);
101 |
102 | /**
103 | * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
104 | *
105 | * Emits a {TransferSingle} event.
106 | *
107 | * Requirements:
108 | *
109 | * - `to` cannot be the zero address.
110 | * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
111 | * - `from` must have a balance of tokens of type `id` of at least `amount`.
112 | * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
113 | * acceptance magic value.
114 | */
115 | function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
116 |
117 | /**
118 | * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
119 | *
120 | * Emits a {TransferBatch} event.
121 | *
122 | * Requirements:
123 | *
124 | * - `ids` and `amounts` must have the same length.
125 | * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
126 | * acceptance magic value.
127 | */
128 | function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
129 | }
130 |
131 | // File: openzeppelin-contracts-master/contracts/token/ERC1155/IERC1155MetadataURI.sol
132 |
133 | pragma solidity ^0.6.2;
134 |
135 |
136 | /**
137 | * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
138 | * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
139 | *
140 | * _Available since v3.1._
141 | */
142 | interface IERC1155MetadataURI is IERC1155 {
143 | /**
144 | * @dev Returns the URI for token type `id`.
145 | *
146 | * If the `\{id\}` substring is present in the URI, it must be replaced by
147 | * clients with the actual token type ID.
148 | */
149 | function uri(uint256 id) external view returns (string memory);
150 | }
151 |
152 | // File: openzeppelin-contracts-master/contracts/token/ERC1155/IERC1155Receiver.sol
153 |
154 | pragma solidity ^0.6.0;
155 |
156 |
157 | /**
158 | * _Available since v3.1._
159 | */
160 | interface IERC1155Receiver is IERC165 {
161 |
162 | /**
163 | @dev Handles the receipt of a single ERC1155 token type. This function is
164 | called at the end of a `safeTransferFrom` after the balance has been updated.
165 | To accept the transfer, this must return
166 | `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
167 | (i.e. 0xf23a6e61, or its own function selector).
168 | @param operator The address which initiated the transfer (i.e. msg.sender)
169 | @param from The address which previously owned the token
170 | @param id The ID of the token being transferred
171 | @param value The amount of tokens being transferred
172 | @param data Additional data with no specified format
173 | @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
174 | */
175 | function onERC1155Received(
176 | address operator,
177 | address from,
178 | uint256 id,
179 | uint256 value,
180 | bytes calldata data
181 | )
182 | external
183 | returns(bytes4);
184 |
185 | /**
186 | @dev Handles the receipt of a multiple ERC1155 token types. This function
187 | is called at the end of a `safeBatchTransferFrom` after the balances have
188 | been updated. To accept the transfer(s), this must return
189 | `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
190 | (i.e. 0xbc197c81, or its own function selector).
191 | @param operator The address which initiated the batch transfer (i.e. msg.sender)
192 | @param from The address which previously owned the token
193 | @param ids An array containing ids of each token being transferred (order and length must match values array)
194 | @param values An array containing amounts of each token being transferred (order and length must match ids array)
195 | @param data Additional data with no specified format
196 | @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
197 | */
198 | function onERC1155BatchReceived(
199 | address operator,
200 | address from,
201 | uint256[] calldata ids,
202 | uint256[] calldata values,
203 | bytes calldata data
204 | )
205 | external
206 | returns(bytes4);
207 | }
208 |
209 | // File: openzeppelin-contracts-master/contracts/GSN/Context.sol
210 |
211 | pragma solidity ^0.6.0;
212 |
213 | /*
214 | * @dev Provides information about the current execution context, including the
215 | * sender of the transaction and its data. While these are generally available
216 | * via msg.sender and msg.data, they should not be accessed in such a direct
217 | * manner, since when dealing with GSN meta-transactions the account sending and
218 | * paying for execution may not be the actual sender (as far as an application
219 | * is concerned).
220 | *
221 | * This contract is only required for intermediate, library-like contracts.
222 | */
223 | abstract contract Context {
224 | function _msgSender() internal view virtual returns (address payable) {
225 | return msg.sender;
226 | }
227 |
228 | function _msgData() internal view virtual returns (bytes memory) {
229 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
230 | return msg.data;
231 | }
232 | }
233 |
234 | // File: openzeppelin-contracts-master/contracts/introspection/ERC165.sol
235 |
236 | pragma solidity ^0.6.0;
237 |
238 |
239 | /**
240 | * @dev Implementation of the {IERC165} interface.
241 | *
242 | * Contracts may inherit from this and call {_registerInterface} to declare
243 | * their support of an interface.
244 | */
245 | contract ERC165 is IERC165 {
246 | /*
247 | * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
248 | */
249 | bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
250 |
251 | /**
252 | * @dev Mapping of interface ids to whether or not it's supported.
253 | */
254 | mapping(bytes4 => bool) private _supportedInterfaces;
255 |
256 | constructor () internal {
257 | // Derived contracts need only register support for their own interfaces,
258 | // we register support for ERC165 itself here
259 | _registerInterface(_INTERFACE_ID_ERC165);
260 | }
261 |
262 | /**
263 | * @dev See {IERC165-supportsInterface}.
264 | *
265 | * Time complexity O(1), guaranteed to always use less than 30 000 gas.
266 | */
267 | function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
268 | return _supportedInterfaces[interfaceId];
269 | }
270 |
271 | /**
272 | * @dev Registers the contract as an implementer of the interface defined by
273 | * `interfaceId`. Support of the actual ERC165 interface is automatic and
274 | * registering its interface id is not required.
275 | *
276 | * See {IERC165-supportsInterface}.
277 | *
278 | * Requirements:
279 | *
280 | * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
281 | */
282 | function _registerInterface(bytes4 interfaceId) internal virtual {
283 | require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
284 | _supportedInterfaces[interfaceId] = true;
285 | }
286 | }
287 |
288 | // File: openzeppelin-contracts-master/contracts/math/SafeMath.sol
289 |
290 | pragma solidity ^0.6.0;
291 |
292 | /**
293 | * @dev Wrappers over Solidity's arithmetic operations with added overflow
294 | * checks.
295 | *
296 | * Arithmetic operations in Solidity wrap on overflow. This can easily result
297 | * in bugs, because programmers usually assume that an overflow raises an
298 | * error, which is the standard behavior in high level programming languages.
299 | * `SafeMath` restores this intuition by reverting the transaction when an
300 | * operation overflows.
301 | *
302 | * Using this library instead of the unchecked operations eliminates an entire
303 | * class of bugs, so it's recommended to use it always.
304 | */
305 | library SafeMath {
306 | /**
307 | * @dev Returns the addition of two unsigned integers, reverting on
308 | * overflow.
309 | *
310 | * Counterpart to Solidity's `+` operator.
311 | *
312 | * Requirements:
313 | *
314 | * - Addition cannot overflow.
315 | */
316 | function add(uint256 a, uint256 b) internal pure returns (uint256) {
317 | uint256 c = a + b;
318 | require(c >= a, "SafeMath: addition overflow");
319 |
320 | return c;
321 | }
322 |
323 | /**
324 | * @dev Returns the subtraction of two unsigned integers, reverting on
325 | * overflow (when the result is negative).
326 | *
327 | * Counterpart to Solidity's `-` operator.
328 | *
329 | * Requirements:
330 | *
331 | * - Subtraction cannot overflow.
332 | */
333 | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
334 | return sub(a, b, "SafeMath: subtraction overflow");
335 | }
336 |
337 | /**
338 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
339 | * overflow (when the result is negative).
340 | *
341 | * Counterpart to Solidity's `-` operator.
342 | *
343 | * Requirements:
344 | *
345 | * - Subtraction cannot overflow.
346 | */
347 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
348 | require(b <= a, errorMessage);
349 | uint256 c = a - b;
350 |
351 | return c;
352 | }
353 |
354 | /**
355 | * @dev Returns the multiplication of two unsigned integers, reverting on
356 | * overflow.
357 | *
358 | * Counterpart to Solidity's `*` operator.
359 | *
360 | * Requirements:
361 | *
362 | * - Multiplication cannot overflow.
363 | */
364 | function mul(uint256 a, uint256 b) internal pure returns (uint256) {
365 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
366 | // benefit is lost if 'b' is also tested.
367 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
368 | if (a == 0) {
369 | return 0;
370 | }
371 |
372 | uint256 c = a * b;
373 | require(c / a == b, "SafeMath: multiplication overflow");
374 |
375 | return c;
376 | }
377 |
378 | /**
379 | * @dev Returns the integer division of two unsigned integers. Reverts on
380 | * division by zero. The result is rounded towards zero.
381 | *
382 | * Counterpart to Solidity's `/` operator. Note: this function uses a
383 | * `revert` opcode (which leaves remaining gas untouched) while Solidity
384 | * uses an invalid opcode to revert (consuming all remaining gas).
385 | *
386 | * Requirements:
387 | *
388 | * - The divisor cannot be zero.
389 | */
390 | function div(uint256 a, uint256 b) internal pure returns (uint256) {
391 | return div(a, b, "SafeMath: division by zero");
392 | }
393 |
394 | /**
395 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
396 | * division by zero. The result is rounded towards zero.
397 | *
398 | * Counterpart to Solidity's `/` operator. Note: this function uses a
399 | * `revert` opcode (which leaves remaining gas untouched) while Solidity
400 | * uses an invalid opcode to revert (consuming all remaining gas).
401 | *
402 | * Requirements:
403 | *
404 | * - The divisor cannot be zero.
405 | */
406 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
407 | require(b > 0, errorMessage);
408 | uint256 c = a / b;
409 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
410 |
411 | return c;
412 | }
413 |
414 | /**
415 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
416 | * Reverts when dividing by zero.
417 | *
418 | * Counterpart to Solidity's `%` operator. This function uses a `revert`
419 | * opcode (which leaves remaining gas untouched) while Solidity uses an
420 | * invalid opcode to revert (consuming all remaining gas).
421 | *
422 | * Requirements:
423 | *
424 | * - The divisor cannot be zero.
425 | */
426 | function mod(uint256 a, uint256 b) internal pure returns (uint256) {
427 | return mod(a, b, "SafeMath: modulo by zero");
428 | }
429 |
430 | /**
431 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
432 | * Reverts with custom message when dividing by zero.
433 | *
434 | * Counterpart to Solidity's `%` operator. This function uses a `revert`
435 | * opcode (which leaves remaining gas untouched) while Solidity uses an
436 | * invalid opcode to revert (consuming all remaining gas).
437 | *
438 | * Requirements:
439 | *
440 | * - The divisor cannot be zero.
441 | */
442 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
443 | require(b != 0, errorMessage);
444 | return a % b;
445 | }
446 | }
447 |
448 | // File: openzeppelin-contracts-master/contracts/utils/Address.sol
449 |
450 | pragma solidity ^0.6.2;
451 |
452 | /**
453 | * @dev Collection of functions related to the address type
454 | */
455 | library Address {
456 | /**
457 | * @dev Returns true if `account` is a contract.
458 | *
459 | * [IMPORTANT]
460 | * ====
461 | * It is unsafe to assume that an address for which this function returns
462 | * false is an externally-owned account (EOA) and not a contract.
463 | *
464 | * Among others, `isContract` will return false for the following
465 | * types of addresses:
466 | *
467 | * - an externally-owned account
468 | * - a contract in construction
469 | * - an address where a contract will be created
470 | * - an address where a contract lived, but was destroyed
471 | * ====
472 | */
473 | function isContract(address account) internal view returns (bool) {
474 | // This method relies on extcodesize, which returns 0 for contracts in
475 | // construction, since the code is only stored at the end of the
476 | // constructor execution.
477 |
478 | uint256 size;
479 | // solhint-disable-next-line no-inline-assembly
480 | assembly { size := extcodesize(account) }
481 | return size > 0;
482 | }
483 |
484 | /**
485 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
486 | * `recipient`, forwarding all available gas and reverting on errors.
487 | *
488 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
489 | * of certain opcodes, possibly making contracts go over the 2300 gas limit
490 | * imposed by `transfer`, making them unable to receive funds via
491 | * `transfer`. {sendValue} removes this limitation.
492 | *
493 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
494 | *
495 | * IMPORTANT: because control is transferred to `recipient`, care must be
496 | * taken to not create reentrancy vulnerabilities. Consider using
497 | * {ReentrancyGuard} or the
498 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
499 | */
500 | function sendValue(address payable recipient, uint256 amount) internal {
501 | require(address(this).balance >= amount, "Address: insufficient balance");
502 |
503 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
504 | (bool success, ) = recipient.call{ value: amount }("");
505 | require(success, "Address: unable to send value, recipient may have reverted");
506 | }
507 |
508 | /**
509 | * @dev Performs a Solidity function call using a low level `call`. A
510 | * plain`call` is an unsafe replacement for a function call: use this
511 | * function instead.
512 | *
513 | * If `target` reverts with a revert reason, it is bubbled up by this
514 | * function (like regular Solidity function calls).
515 | *
516 | * Returns the raw returned data. To convert to the expected return value,
517 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
518 | *
519 | * Requirements:
520 | *
521 | * - `target` must be a contract.
522 | * - calling `target` with `data` must not revert.
523 | *
524 | * _Available since v3.1._
525 | */
526 | function functionCall(address target, bytes memory data) internal returns (bytes memory) {
527 | return functionCall(target, data, "Address: low-level call failed");
528 | }
529 |
530 | /**
531 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
532 | * `errorMessage` as a fallback revert reason when `target` reverts.
533 | *
534 | * _Available since v3.1._
535 | */
536 | function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
537 | return functionCallWithValue(target, data, 0, errorMessage);
538 | }
539 |
540 | /**
541 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
542 | * but also transferring `value` wei to `target`.
543 | *
544 | * Requirements:
545 | *
546 | * - the calling contract must have an ETH balance of at least `value`.
547 | * - the called Solidity function must be `payable`.
548 | *
549 | * _Available since v3.1._
550 | */
551 | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
552 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
553 | }
554 |
555 | /**
556 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
557 | * with `errorMessage` as a fallback revert reason when `target` reverts.
558 | *
559 | * _Available since v3.1._
560 | */
561 | function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
562 | require(address(this).balance >= value, "Address: insufficient balance for call");
563 | require(isContract(target), "Address: call to non-contract");
564 |
565 | // solhint-disable-next-line avoid-low-level-calls
566 | (bool success, bytes memory returndata) = target.call{ value: value }(data);
567 | return _verifyCallResult(success, returndata, errorMessage);
568 | }
569 |
570 | /**
571 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
572 | * but performing a static call.
573 | *
574 | * _Available since v3.3._
575 | */
576 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
577 | return functionStaticCall(target, data, "Address: low-level static call failed");
578 | }
579 |
580 | /**
581 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
582 | * but performing a static call.
583 | *
584 | * _Available since v3.3._
585 | */
586 | function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
587 | require(isContract(target), "Address: static call to non-contract");
588 |
589 | // solhint-disable-next-line avoid-low-level-calls
590 | (bool success, bytes memory returndata) = target.staticcall(data);
591 | return _verifyCallResult(success, returndata, errorMessage);
592 | }
593 |
594 | /**
595 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
596 | * but performing a delegate call.
597 | *
598 | * _Available since v3.3._
599 | */
600 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
601 | return functionDelegateCall(target, data, "Address: low-level delegate call failed");
602 | }
603 |
604 | /**
605 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
606 | * but performing a delegate call.
607 | *
608 | * _Available since v3.3._
609 | */
610 | function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
611 | require(isContract(target), "Address: delegate call to non-contract");
612 |
613 | // solhint-disable-next-line avoid-low-level-calls
614 | (bool success, bytes memory returndata) = target.delegatecall(data);
615 | return _verifyCallResult(success, returndata, errorMessage);
616 | }
617 |
618 | function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
619 | if (success) {
620 | return returndata;
621 | } else {
622 | // Look for revert reason and bubble it up if present
623 | if (returndata.length > 0) {
624 | // The easiest way to bubble the revert reason is using memory via assembly
625 |
626 | // solhint-disable-next-line no-inline-assembly
627 | assembly {
628 | let returndata_size := mload(returndata)
629 | revert(add(32, returndata), returndata_size)
630 | }
631 | } else {
632 | revert(errorMessage);
633 | }
634 | }
635 | }
636 | }
637 |
638 | // @dev Implementation for different URIs for every token
639 | contract TokenURI {
640 | // mapping for token URIs
641 | mapping(uint256 => string) private _tokenURIs;
642 |
643 | function _tokenURI(uint256 tokenId) internal view returns (string memory) {
644 | return _tokenURIs[tokenId];
645 | }
646 |
647 | function _setTokenURI(uint256 tokenId, string memory tokenUri) virtual internal {
648 | _tokenURIs[tokenId] = tokenUri;
649 | }
650 | }
651 |
652 | // File: openzeppelin-contracts-master/contracts/token/ERC1155/ERC1155.sol
653 | pragma solidity ^0.6.0;
654 |
655 |
656 | /**
657 | *
658 | * @dev Implementation of the basic standard multi-token.
659 | * See https://eips.ethereum.org/EIPS/eip-1155
660 | * Originally based on code by Enjin: https://github.com/enjin/erc-1155
661 | *
662 | * _Available since v3.1._
663 | */
664 | contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, TokenURI {
665 | using SafeMath for uint256;
666 | using Address for address;
667 |
668 | // Mapping from token ID to account balances
669 | mapping (uint256 => mapping(address => uint256)) private _balances;
670 |
671 | // Mapping from account to operator approvals
672 | mapping (address => mapping(address => bool)) private _operatorApprovals;
673 |
674 | // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
675 | string private _uri;
676 |
677 | /*
678 | * bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
679 | * bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
680 | * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
681 | * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
682 | * bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
683 | * bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
684 | *
685 | * => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
686 | * 0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
687 | */
688 | bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;
689 |
690 | /*
691 | * bytes4(keccak256('uri(uint256)')) == 0x0e89341c
692 | */
693 | bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;
694 |
695 | /**
696 | * @dev See {_setURI}.
697 | */
698 | constructor (string memory uri) public {
699 | _setURI(uri);
700 |
701 | // register the supported interfaces to conform to ERC1155 via ERC165
702 | _registerInterface(_INTERFACE_ID_ERC1155);
703 |
704 | // register the supported interfaces to conform to ERC1155MetadataURI via ERC165
705 | _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
706 | }
707 |
708 | /**
709 | * @dev See {IERC1155MetadataURI-uri}.
710 | *
711 | * This implementation returns the same URI for *all* token types. It relies
712 | * on the token type ID substitution mechanism
713 | * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
714 | *
715 | * Clients calling this function must replace the `\{id\}` substring with the
716 | * actual token type ID.
717 | */
718 | function uri(uint256 id) external view virtual override returns (string memory) {
719 | return _tokenURI(id);
720 | }
721 |
722 | /**
723 | * @dev See {IERC1155-balanceOf}.
724 | *
725 | * Requirements:
726 | *
727 | * - `account` cannot be the zero address.
728 | */
729 | function balanceOf(address account, uint256 id) public view override returns (uint256) {
730 | require(account != address(0), "ERC1155: balance query for the zero address");
731 | return _balances[id][account];
732 | }
733 |
734 | /**
735 | * @dev See {IERC1155-balanceOfBatch}.
736 | *
737 | * Requirements:
738 | *
739 | * - `accounts` and `ids` must have the same length.
740 | */
741 | function balanceOfBatch(
742 | address[] memory accounts,
743 | uint256[] memory ids
744 | )
745 | public
746 | view
747 | override
748 | returns (uint256[] memory)
749 | {
750 | require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
751 |
752 | uint256[] memory batchBalances = new uint256[](accounts.length);
753 |
754 | for (uint256 i = 0; i < accounts.length; ++i) {
755 | require(accounts[i] != address(0), "ERC1155: batch balance query for the zero address");
756 | batchBalances[i] = _balances[ids[i]][accounts[i]];
757 | }
758 |
759 | return batchBalances;
760 | }
761 |
762 | /**
763 | * @dev See {IERC1155-setApprovalForAll}.
764 | */
765 | function setApprovalForAll(address operator, bool approved) public virtual override {
766 | require(_msgSender() != operator, "ERC1155: setting approval status for self");
767 |
768 | _operatorApprovals[_msgSender()][operator] = approved;
769 | emit ApprovalForAll(_msgSender(), operator, approved);
770 | }
771 |
772 | /**
773 | * @dev See {IERC1155-isApprovedForAll}.
774 | */
775 | function isApprovedForAll(address account, address operator) public view override returns (bool) {
776 | return _operatorApprovals[account][operator];
777 | }
778 |
779 | /**
780 | * @dev See {IERC1155-safeTransferFrom}.
781 | */
782 | function safeTransferFrom(
783 | address from,
784 | address to,
785 | uint256 id,
786 | uint256 amount,
787 | bytes memory data
788 | )
789 | public
790 | virtual
791 | override
792 | {
793 | require(to != address(0), "ERC1155: transfer to the zero address");
794 | require(
795 | from == _msgSender() || isApprovedForAll(from, _msgSender()),
796 | "ERC1155: caller is not owner nor approved"
797 | );
798 |
799 | address operator = _msgSender();
800 |
801 | _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
802 |
803 | _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
804 | _balances[id][to] = _balances[id][to].add(amount);
805 |
806 | emit TransferSingle(operator, from, to, id, amount);
807 |
808 | _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
809 | }
810 |
811 | /**
812 | * @dev See {IERC1155-safeBatchTransferFrom}.
813 | */
814 | function safeBatchTransferFrom(
815 | address from,
816 | address to,
817 | uint256[] memory ids,
818 | uint256[] memory amounts,
819 | bytes memory data
820 | )
821 | public
822 | virtual
823 | override
824 | {
825 | require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
826 | require(to != address(0), "ERC1155: transfer to the zero address");
827 | require(
828 | from == _msgSender() || isApprovedForAll(from, _msgSender()),
829 | "ERC1155: transfer caller is not owner nor approved"
830 | );
831 |
832 | address operator = _msgSender();
833 |
834 | _beforeTokenTransfer(operator, from, to, ids, amounts, data);
835 |
836 | for (uint256 i = 0; i < ids.length; ++i) {
837 | uint256 id = ids[i];
838 | uint256 amount = amounts[i];
839 |
840 | _balances[id][from] = _balances[id][from].sub(
841 | amount,
842 | "ERC1155: insufficient balance for transfer"
843 | );
844 | _balances[id][to] = _balances[id][to].add(amount);
845 | }
846 |
847 | emit TransferBatch(operator, from, to, ids, amounts);
848 |
849 | _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
850 | }
851 |
852 | /**
853 | * @dev Sets a new URI for all token types, by relying on the token type ID
854 | * substitution mechanism
855 | * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
856 | *
857 | * By this mechanism, any occurrence of the `\{id\}` substring in either the
858 | * URI or any of the amounts in the JSON file at said URI will be replaced by
859 | * clients with the token type ID.
860 | *
861 | * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
862 | * interpreted by clients as
863 | * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
864 | * for token type ID 0x4cce0.
865 | *
866 | * See {uri}.
867 | *
868 | * Because these URIs cannot be meaningfully represented by the {URI} event,
869 | * this function emits no events.
870 | */
871 | function _setURI(string memory newuri) internal virtual {
872 | _uri = newuri;
873 | }
874 |
875 | /**
876 | * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
877 | *
878 | * Emits a {TransferSingle} event.
879 | *
880 | * Requirements:
881 | *
882 | * - `account` cannot be the zero address.
883 | * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
884 | * acceptance magic value.
885 | */
886 | function _mint(address account, uint256 tokenId, uint256 amount, string memory tokenUri, bytes memory data) internal virtual {
887 | require(account != address(0), "ERC1155: mint to the zero address");
888 |
889 | address operator = _msgSender();
890 |
891 | _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(tokenId), _asSingletonArray(amount), data);
892 |
893 | _balances[tokenId][account] = _balances[tokenId][account].add(amount);
894 | _setTokenURI(tokenId, tokenUri);
895 |
896 | emit TransferSingle(operator, address(0), account, tokenId, amount);
897 |
898 | _doSafeTransferAcceptanceCheck(operator, address(0), account, tokenId, amount, data);
899 | }
900 |
901 | /**
902 | * @dev Internal function to set the token URI for a given token.
903 | * Reverts if the token ID does not exist.
904 | * @param tokenId uint256 ID of the token to set its URI
905 | * @param tokenUri string URI to assign
906 | */
907 | function _setTokenURI(uint256 tokenId, string memory tokenUri) internal override {
908 | super._setTokenURI(tokenId, tokenUri);
909 | }
910 |
911 | /**
912 | * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
913 | *
914 | * Requirements:
915 | *
916 | * - `ids` and `amounts` must have the same length.
917 | * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
918 | * acceptance magic value.
919 | */
920 | function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {
921 | require(to != address(0), "ERC1155: mint to the zero address");
922 | require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
923 |
924 | address operator = _msgSender();
925 |
926 | _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
927 |
928 | for (uint i = 0; i < ids.length; i++) {
929 | _balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
930 | }
931 |
932 | emit TransferBatch(operator, address(0), to, ids, amounts);
933 |
934 | _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
935 | }
936 |
937 | /**
938 | * @dev Destroys `amount` tokens of token type `id` from `account`
939 | *
940 | * Requirements:
941 | *
942 | * - `account` cannot be the zero address.
943 | * - `account` must have at least `amount` tokens of token type `id`.
944 | */
945 | function _burn(address account, uint256 id, uint256 amount) internal virtual {
946 | require(account != address(0), "ERC1155: burn from the zero address");
947 |
948 | address operator = _msgSender();
949 |
950 | _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
951 |
952 | _balances[id][account] = _balances[id][account].sub(
953 | amount,
954 | "ERC1155: burn amount exceeds balance"
955 | );
956 |
957 | emit TransferSingle(operator, account, address(0), id, amount);
958 | }
959 |
960 | /**
961 | * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
962 | *
963 | * Requirements:
964 | *
965 | * - `ids` and `amounts` must have the same length.
966 | */
967 | function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {
968 | require(account != address(0), "ERC1155: burn from the zero address");
969 | require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
970 |
971 | address operator = _msgSender();
972 |
973 | _beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
974 |
975 | for (uint i = 0; i < ids.length; i++) {
976 | _balances[ids[i]][account] = _balances[ids[i]][account].sub(
977 | amounts[i],
978 | "ERC1155: burn amount exceeds balance"
979 | );
980 | }
981 |
982 | emit TransferBatch(operator, account, address(0), ids, amounts);
983 | }
984 |
985 | /**
986 | * @dev Hook that is called before any token transfer. This includes minting
987 | * and burning, as well as batched variants.
988 | *
989 | * The same hook is called on both single and batched variants. For single
990 | * transfers, the length of the `id` and `amount` arrays will be 1.
991 | *
992 | * Calling conditions (for each `id` and `amount` pair):
993 | *
994 | * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
995 | * of token type `id` will be transferred to `to`.
996 | * - When `from` is zero, `amount` tokens of token type `id` will be minted
997 | * for `to`.
998 | * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
999 | * will be burned.
1000 | * - `from` and `to` are never both zero.
1001 | * - `ids` and `amounts` have the same, non-zero length.
1002 | *
1003 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
1004 | */
1005 | function _beforeTokenTransfer(
1006 | address operator,
1007 | address from,
1008 | address to,
1009 | uint256[] memory ids,
1010 | uint256[] memory amounts,
1011 | bytes memory data
1012 | )
1013 | internal virtual
1014 | { }
1015 |
1016 | function _doSafeTransferAcceptanceCheck(
1017 | address operator,
1018 | address from,
1019 | address to,
1020 | uint256 id,
1021 | uint256 amount,
1022 | bytes memory data
1023 | )
1024 | private
1025 | {
1026 | if (to.isContract()) {
1027 | try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
1028 | if (response != IERC1155Receiver(to).onERC1155Received.selector) {
1029 | revert("ERC1155: ERC1155Receiver rejected tokens");
1030 | }
1031 | } catch Error(string memory reason) {
1032 | revert(reason);
1033 | } catch {
1034 | revert("ERC1155: transfer to non ERC1155Receiver implementer");
1035 | }
1036 | }
1037 | }
1038 |
1039 | function _doSafeBatchTransferAcceptanceCheck(
1040 | address operator,
1041 | address from,
1042 | address to,
1043 | uint256[] memory ids,
1044 | uint256[] memory amounts,
1045 | bytes memory data
1046 | )
1047 | private
1048 | {
1049 | if (to.isContract()) {
1050 | try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {
1051 | if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {
1052 | revert("ERC1155: ERC1155Receiver rejected tokens");
1053 | }
1054 | } catch Error(string memory reason) {
1055 | revert(reason);
1056 | } catch {
1057 | revert("ERC1155: transfer to non ERC1155Receiver implementer");
1058 | }
1059 | }
1060 | }
1061 |
1062 | function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
1063 | uint256[] memory array = new uint256[](1);
1064 | array[0] = element;
1065 |
1066 | return array;
1067 | }
1068 | }
1069 |
--------------------------------------------------------------------------------