ETH Price: $1,898.63 (+0.60%)

Transaction Decoder

Block:
11056615 at Oct-14-2020 10:45:32 PM +UTC
Transaction Fee:
0.233041975 ETH $442.46
Gas Used:
9,321,679 Gas / 25 Gwei

Emitted Events:

24 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=60 )
25 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=60, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=11 )
26 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=61 )
27 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=61, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=11 )
28 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=62 )
29 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=62, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=11 )
30 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=63 )
31 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=63, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=11 )
32 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=64 )
33 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=64, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=11 )
34 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=65 )
35 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=65, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=11 )
36 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=66 )
37 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=66, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=12 )
38 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=67 )
39 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=67, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=12 )
40 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=68 )
41 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=68, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=12 )
42 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=69 )
43 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=69, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=12 )
44 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=70 )
45 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=70, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=12 )
46 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=71 )
47 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=71, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=12 )
48 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=72 )
49 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=72, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=13 )
50 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=73 )
51 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=73, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=13 )
52 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=74 )
53 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=74, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=13 )
54 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=75 )
55 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=75, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=13 )
56 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=76 )
57 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=76, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=13 )
58 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=77 )
59 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=77, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=13 )
60 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=78 )
61 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=78, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=14 )
62 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=79 )
63 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=79, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=14 )
64 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=80 )
65 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=80, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=14 )
66 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=81 )
67 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=81, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=14 )
68 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=82 )
69 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=82, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=14 )
70 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=83 )
71 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=83, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=14 )
72 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=84 )
73 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=84, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=15 )
74 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=85 )
75 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=85, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=15 )
76 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=86 )
77 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=86, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=15 )
78 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=87 )
79 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=87, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=15 )
80 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=88 )
81 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=88, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=15 )
82 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=89 )
83 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=89, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=15 )
84 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=90 )
85 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=90, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=16 )
86 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=91 )
87 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=91, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=16 )
88 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=92 )
89 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=92, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=16 )
90 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=93 )
91 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=93, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=16 )
92 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=94 )
93 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=94, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=16 )
94 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=95 )
95 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=95, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=16 )
96 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=96 )
97 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=96, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=17 )
98 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=97 )
99 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=97, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=17 )
100 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=98 )
101 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=98, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=17 )
102 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=99 )
103 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=99, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=17 )
104 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=100 )
105 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=100, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=17 )
106 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=101 )
107 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=101, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=17 )
108 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=102 )
109 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=102, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=18 )
110 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=103 )
111 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=103, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=18 )
112 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=104 )
113 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=104, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=18 )
114 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=105 )
115 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=105, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=18 )
116 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=106 )
117 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=106, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=18 )
118 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=107 )
119 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=107, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=18 )
120 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=108 )
121 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=108, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=19 )
122 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=109 )
123 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=109, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=19 )
124 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=110 )
125 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=110, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=19 )
126 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=111 )
127 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=111, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=19 )
128 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=112 )
129 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=112, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=19 )
130 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=113 )
131 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=113, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=19 )
132 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=114 )
133 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=114, _wearableIdKey=B8DD597FC226ACD248E4BDBD92D1EC1A03E8EC63C12AE4FE551836783D0771B9, _wearableId=steampunk_goggles, _issuedId=20 )
134 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=115 )
135 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=115, _wearableIdKey=2FA10373B7A697C13C9E96A6842310C1BDCA75153E898F147D60A102448E95BF, _wearableId=steampunk_boots, _issuedId=20 )
136 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=116 )
137 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=116, _wearableIdKey=28871C9A352DD643610899D9BEAFAD22892A47596F60A1A7B9DCE8EDFB71270A, _wearableId=steampunk_hat, _issuedId=20 )
138 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=117 )
139 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=117, _wearableIdKey=C728987DD7653FDBBEF88E56015F0E28E0FBC9500AB9FE0CBE352B4C4E3877BD, _wearableId=steampunk_trousers, _issuedId=20 )
140 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=118 )
141 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=118, _wearableIdKey=BB0FEC33CB95090EEB1EED5216D025E784266915A19D3B8446C9AD7D2AC7D0F1, _wearableId=steampunk_mask, _issuedId=20 )
142 ERC721Collection.Transfer( from=0x00000000...000000000, to=0x338AD191...8E8e8268f, tokenId=119 )
143 ERC721Collection.Issue( _beneficiary=0x338AD191...8E8e8268f, _tokenId=119, _wearableIdKey=51824FCE8C4EFD5EEC7E1A79862558B401C40F3D6CEE40C79960420528B1C246, _wearableId=steampunk_jacket, _issuedId=20 )

Account State Difference:

  Address   Before After State Difference Code
0x1FBf2678...B455D1160
(Decentraland: Deployer 5)
2.573769895 Eth
Nonce: 68
2.34072792 Eth
Nonce: 69
0.233041975
(F2Pool Old)
4,096.372914732600579717 Eth4,096.605956707600579717 Eth0.233041975
0xb96697FA...caAd1B8E1

Execution Trace

ERC721Collection.issueTokens( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
  • ERC721Collection.STATICCALL( )
    /**
     *Submitted for verification at Etherscan.io on 2020-09-16
    */
    
    /**
     *Submitted for verification at Etherscan.io on 2020-07-02
    */
    
    // File: @openzeppelin/contracts/ownership/Ownable.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be aplied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            _owner = msg.sender;
            emit OwnershipTransferred(address(0), _owner);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return msg.sender == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * > Note: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    // File: @openzeppelin/contracts/introspection/IERC165.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC165 standard, as defined in the
     * [EIP](https://eips.ethereum.org/EIPS/eip-165).
     *
     * Implementers can declare support of contract interfaces, which can then be
     * queried by others (`ERC165Checker`).
     *
     * For an implementation, see `ERC165`.
     */
    interface IERC165 {
        /**
         * @dev Returns true if this contract implements the interface defined by
         * `interfaceId`. See the corresponding
         * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
         * to learn more about how these ids are created.
         *
         * This function call must use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    // File: @openzeppelin/contracts/token/ERC721/IERC721.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Required interface of an ERC721 compliant contract.
     */
    contract IERC721 is IERC165 {
        event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
        event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
        /**
         * @dev Returns the number of NFTs in `owner`'s account.
         */
        function balanceOf(address owner) public view returns (uint256 balance);
    
        /**
         * @dev Returns the owner of the NFT specified by `tokenId`.
         */
        function ownerOf(uint256 tokenId) public view returns (address owner);
    
        /**
         * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
         * another (`to`).
         *
         * 
         *
         * Requirements:
         * - `from`, `to` cannot be zero.
         * - `tokenId` must be owned by `from`.
         * - If the caller is not `from`, it must be have been allowed to move this
         * NFT by either `approve` or `setApproveForAll`.
         */
        function safeTransferFrom(address from, address to, uint256 tokenId) public;
        /**
         * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
         * another (`to`).
         *
         * Requirements:
         * - If the caller is not `from`, it must be approved to move this NFT by
         * either `approve` or `setApproveForAll`.
         */
        function transferFrom(address from, address to, uint256 tokenId) public;
        function approve(address to, uint256 tokenId) public;
        function getApproved(uint256 tokenId) public view returns (address operator);
    
        function setApprovalForAll(address operator, bool _approved) public;
        function isApprovedForAll(address owner, address operator) public view returns (bool);
    
    
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
    }
    
    // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title ERC721 token receiver interface
     * @dev Interface for any contract that wants to support safeTransfers
     * from ERC721 asset contracts.
     */
    contract IERC721Receiver {
        /**
         * @notice Handle the receipt of an NFT
         * @dev The ERC721 smart contract calls this function on the recipient
         * after a `safeTransfer`. This function MUST return the function selector,
         * otherwise the caller will revert the transaction. The selector to be
         * returned can be obtained as `this.onERC721Received.selector`. This
         * function MAY throw to revert and reject the transfer.
         * Note: the ERC721 contract address is always the message sender.
         * @param operator The address which called `safeTransferFrom` function
         * @param from The address which previously owned the token
         * @param tokenId The NFT identifier which is being transferred
         * @param data Additional data with no specified format
         * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
         */
        function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
        public returns (bytes4);
    }
    
    // File: @openzeppelin/contracts/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a, "SafeMath: subtraction overflow");
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, "SafeMath: division by zero");
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    
    // File: @openzeppelin/contracts/utils/Address.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Collection of functions related to the address type,
     */
    library Address {
        /**
         * @dev Returns true if `account` is a contract.
         *
         * This test is non-exhaustive, and there may be false-negatives: during the
         * execution of a contract's constructor, its address will be reported as
         * not containing a contract.
         *
         * > It is unsafe to assume that an address for which this function returns
         * false is an externally-owned account (EOA) and not a contract.
         */
        function isContract(address account) internal view returns (bool) {
            // This method relies in extcodesize, which returns 0 for contracts in
            // construction, since the code is only stored at the end of the
            // constructor execution.
    
            uint256 size;
            // solhint-disable-next-line no-inline-assembly
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }
    
    // File: @openzeppelin/contracts/drafts/Counters.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title Counters
     * @author Matt Condon (@shrugs)
     * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
     * of elements in a mapping, issuing ERC721 ids, or counting request ids.
     *
     * Include with `using Counters for Counters.Counter;`
     * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
     * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
     * directly accessed.
     */
    library Counters {
        using SafeMath for uint256;
    
        struct Counter {
            // This variable should never be directly accessed by users of the library: interactions must be restricted to
            // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
            // this feature: see https://github.com/ethereum/solidity/issues/4637
            uint256 _value; // default: 0
        }
    
        function current(Counter storage counter) internal view returns (uint256) {
            return counter._value;
        }
    
        function increment(Counter storage counter) internal {
            counter._value += 1;
        }
    
        function decrement(Counter storage counter) internal {
            counter._value = counter._value.sub(1);
        }
    }
    
    // File: @openzeppelin/contracts/introspection/ERC165.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Implementation of the `IERC165` interface.
     *
     * Contracts may inherit from this and call `_registerInterface` to declare
     * their support of an interface.
     */
    contract ERC165 is IERC165 {
        /*
         * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
         */
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        /**
         * @dev Mapping of interface ids to whether or not it's supported.
         */
        mapping(bytes4 => bool) private _supportedInterfaces;
    
        constructor () internal {
            // Derived contracts need only register support for their own interfaces,
            // we register support for ERC165 itself here
            _registerInterface(_INTERFACE_ID_ERC165);
        }
    
        /**
         * @dev See `IERC165.supportsInterface`.
         *
         * Time complexity O(1), guaranteed to always use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool) {
            return _supportedInterfaces[interfaceId];
        }
    
        /**
         * @dev Registers the contract as an implementer of the interface defined by
         * `interfaceId`. Support of the actual ERC165 interface is automatic and
         * registering its interface id is not required.
         *
         * See `IERC165.supportsInterface`.
         *
         * Requirements:
         *
         * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
         */
        function _registerInterface(bytes4 interfaceId) internal {
            require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
            _supportedInterfaces[interfaceId] = true;
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC721/ERC721.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    
    
    
    /**
     * @title ERC721 Non-Fungible Token Standard basic implementation
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721 is ERC165, IERC721 {
        using SafeMath for uint256;
        using Address for address;
        using Counters for Counters.Counter;
    
        // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
        // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
        bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
    
        // Mapping from token ID to owner
        mapping (uint256 => address) private _tokenOwner;
    
        // Mapping from token ID to approved address
        mapping (uint256 => address) private _tokenApprovals;
    
        // Mapping from owner to number of owned token
        mapping (address => Counters.Counter) private _ownedTokensCount;
    
        // Mapping from owner to operator approvals
        mapping (address => mapping (address => bool)) private _operatorApprovals;
    
        /*
         *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
         *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
         *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
         *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
         *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
         *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c
         *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
         *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
         *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
         *
         *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
         *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
         */
        bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    
        constructor () public {
            // register the supported interfaces to conform to ERC721 via ERC165
            _registerInterface(_INTERFACE_ID_ERC721);
        }
    
        /**
         * @dev Gets the balance of the specified address.
         * @param owner address to query the balance of
         * @return uint256 representing the amount owned by the passed address
         */
        function balanceOf(address owner) public view returns (uint256) {
            require(owner != address(0), "ERC721: balance query for the zero address");
    
            return _ownedTokensCount[owner].current();
        }
    
        /**
         * @dev Gets the owner of the specified token ID.
         * @param tokenId uint256 ID of the token to query the owner of
         * @return address currently marked as the owner of the given token ID
         */
        function ownerOf(uint256 tokenId) public view returns (address) {
            address owner = _tokenOwner[tokenId];
            require(owner != address(0), "ERC721: owner query for nonexistent token");
    
            return owner;
        }
    
        /**
         * @dev Approves another address to transfer the given token ID
         * The zero address indicates there is no approved address.
         * There can only be one approved address per token at a given time.
         * Can only be called by the token owner or an approved operator.
         * @param to address to be approved for the given token ID
         * @param tokenId uint256 ID of the token to be approved
         */
        function approve(address to, uint256 tokenId) public {
            address owner = ownerOf(tokenId);
            require(to != owner, "ERC721: approval to current owner");
    
            require(msg.sender == owner || isApprovedForAll(owner, msg.sender),
                "ERC721: approve caller is not owner nor approved for all"
            );
    
            _tokenApprovals[tokenId] = to;
            emit Approval(owner, to, tokenId);
        }
    
        /**
         * @dev Gets the approved address for a token ID, or zero if no address set
         * Reverts if the token ID does not exist.
         * @param tokenId uint256 ID of the token to query the approval of
         * @return address currently approved for the given token ID
         */
        function getApproved(uint256 tokenId) public view returns (address) {
            require(_exists(tokenId), "ERC721: approved query for nonexistent token");
    
            return _tokenApprovals[tokenId];
        }
    
        /**
         * @dev Sets or unsets the approval of a given operator
         * An operator is allowed to transfer all tokens of the sender on their behalf.
         * @param to operator address to set the approval
         * @param approved representing the status of the approval to be set
         */
        function setApprovalForAll(address to, bool approved) public {
            require(to != msg.sender, "ERC721: approve to caller");
    
            _operatorApprovals[msg.sender][to] = approved;
            emit ApprovalForAll(msg.sender, to, approved);
        }
    
        /**
         * @dev Tells whether an operator is approved by a given owner.
         * @param owner owner address which you want to query the approval of
         * @param operator operator address which you want to query the approval of
         * @return bool whether the given operator is approved by the given owner
         */
        function isApprovedForAll(address owner, address operator) public view returns (bool) {
            return _operatorApprovals[owner][operator];
        }
    
        /**
         * @dev Transfers the ownership of a given token ID to another address.
         * Usage of this method is discouraged, use `safeTransferFrom` whenever possible.
         * Requires the msg.sender to be the owner, approved, or operator.
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function transferFrom(address from, address to, uint256 tokenId) public {
            //solhint-disable-next-line max-line-length
            require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
    
            _transferFrom(from, to, tokenId);
        }
    
        /**
         * @dev Safely transfers the ownership of a given token ID to another address
         * If the target address is a contract, it must implement `onERC721Received`,
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function safeTransferFrom(address from, address to, uint256 tokenId) public {
            safeTransferFrom(from, to, tokenId, "");
        }
    
        /**
         * @dev Safely transfers the ownership of a given token ID to another address
         * If the target address is a contract, it must implement `onERC721Received`,
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         * @param _data bytes data to send along with a safe transfer check
         */
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
            transferFrom(from, to, tokenId);
            require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
        }
    
        /**
         * @dev Returns whether the specified token exists.
         * @param tokenId uint256 ID of the token to query the existence of
         * @return bool whether the token exists
         */
        function _exists(uint256 tokenId) internal view returns (bool) {
            address owner = _tokenOwner[tokenId];
            return owner != address(0);
        }
    
        /**
         * @dev Returns whether the given spender can transfer a given token ID.
         * @param spender address of the spender to query
         * @param tokenId uint256 ID of the token to be transferred
         * @return bool whether the msg.sender is approved for the given token ID,
         * is an operator of the owner, or is the owner of the token
         */
        function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
            require(_exists(tokenId), "ERC721: operator query for nonexistent token");
            address owner = ownerOf(tokenId);
            return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
        }
    
        /**
         * @dev Internal function to mint a new token.
         * Reverts if the given token ID already exists.
         * @param to The address that will own the minted token
         * @param tokenId uint256 ID of the token to be minted
         */
        function _mint(address to, uint256 tokenId) internal {
            require(to != address(0), "ERC721: mint to the zero address");
            require(!_exists(tokenId), "ERC721: token already minted");
    
            _tokenOwner[tokenId] = to;
            _ownedTokensCount[to].increment();
    
            emit Transfer(address(0), to, tokenId);
        }
    
        /**
         * @dev Internal function to burn a specific token.
         * Reverts if the token does not exist.
         * Deprecated, use _burn(uint256) instead.
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(address owner, uint256 tokenId) internal {
            require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
    
            _clearApproval(tokenId);
    
            _ownedTokensCount[owner].decrement();
            _tokenOwner[tokenId] = address(0);
    
            emit Transfer(owner, address(0), tokenId);
        }
    
        /**
         * @dev Internal function to burn a specific token.
         * Reverts if the token does not exist.
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(uint256 tokenId) internal {
            _burn(ownerOf(tokenId), tokenId);
        }
    
        /**
         * @dev Internal function to transfer ownership of a given token ID to another address.
         * As opposed to transferFrom, this imposes no restrictions on msg.sender.
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function _transferFrom(address from, address to, uint256 tokenId) internal {
            require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
            require(to != address(0), "ERC721: transfer to the zero address");
    
            _clearApproval(tokenId);
    
            _ownedTokensCount[from].decrement();
            _ownedTokensCount[to].increment();
    
            _tokenOwner[tokenId] = to;
    
            emit Transfer(from, to, tokenId);
        }
    
        /**
         * @dev Internal function to invoke `onERC721Received` on a target address.
         * The call is not executed if the target address is not a contract.
         *
         * This function is deprecated.
         * @param from address representing the previous owner of the given token ID
         * @param to target address that will receive the tokens
         * @param tokenId uint256 ID of the token to be transferred
         * @param _data bytes optional data to send along with the call
         * @return bool whether the call correctly returned the expected magic value
         */
        function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
            internal returns (bool)
        {
            if (!to.isContract()) {
                return true;
            }
    
            bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
            return (retval == _ERC721_RECEIVED);
        }
    
        /**
         * @dev Private function to clear current approval of a given token ID.
         * @param tokenId uint256 ID of the token to be transferred
         */
        function _clearApproval(uint256 tokenId) private {
            if (_tokenApprovals[tokenId] != address(0)) {
                _tokenApprovals[tokenId] = address(0);
            }
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract IERC721Enumerable is IERC721 {
        function totalSupply() public view returns (uint256);
        function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);
    
        function tokenByIndex(uint256 index) public view returns (uint256);
    }
    
    // File: @openzeppelin/contracts/token/ERC721/ERC721Enumerable.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
        // Mapping from owner to list of owned token IDs
        mapping(address => uint256[]) private _ownedTokens;
    
        // Mapping from token ID to index of the owner tokens list
        mapping(uint256 => uint256) private _ownedTokensIndex;
    
        // Array with all token ids, used for enumeration
        uint256[] private _allTokens;
    
        // Mapping from token id to position in the allTokens array
        mapping(uint256 => uint256) private _allTokensIndex;
    
        /*
         *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
         *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
         *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
         *
         *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
         */
        bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
    
        /**
         * @dev Constructor function.
         */
        constructor () public {
            // register the supported interface to conform to ERC721Enumerable via ERC165
            _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
        }
    
        /**
         * @dev Gets the token ID at a given index of the tokens list of the requested owner.
         * @param owner address owning the tokens list to be accessed
         * @param index uint256 representing the index to be accessed of the requested tokens list
         * @return uint256 token ID at the given index of the tokens list owned by the requested address
         */
        function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
            require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
            return _ownedTokens[owner][index];
        }
    
        /**
         * @dev Gets the total amount of tokens stored by the contract.
         * @return uint256 representing the total amount of tokens
         */
        function totalSupply() public view returns (uint256) {
            return _allTokens.length;
        }
    
        /**
         * @dev Gets the token ID at a given index of all the tokens in this contract
         * Reverts if the index is greater or equal to the total number of tokens.
         * @param index uint256 representing the index to be accessed of the tokens list
         * @return uint256 token ID at the given index of the tokens list
         */
        function tokenByIndex(uint256 index) public view returns (uint256) {
            require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
            return _allTokens[index];
        }
    
        /**
         * @dev Internal function to transfer ownership of a given token ID to another address.
         * As opposed to transferFrom, this imposes no restrictions on msg.sender.
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function _transferFrom(address from, address to, uint256 tokenId) internal {
            super._transferFrom(from, to, tokenId);
    
            _removeTokenFromOwnerEnumeration(from, tokenId);
    
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    
        /**
         * @dev Internal function to mint a new token.
         * Reverts if the given token ID already exists.
         * @param to address the beneficiary that will own the minted token
         * @param tokenId uint256 ID of the token to be minted
         */
        function _mint(address to, uint256 tokenId) internal {
            super._mint(to, tokenId);
    
            _addTokenToOwnerEnumeration(to, tokenId);
    
            _addTokenToAllTokensEnumeration(tokenId);
        }
    
        /**
         * @dev Internal function to burn a specific token.
         * Reverts if the token does not exist.
         * Deprecated, use _burn(uint256) instead.
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(address owner, uint256 tokenId) internal {
            super._burn(owner, tokenId);
    
            _removeTokenFromOwnerEnumeration(owner, tokenId);
            // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
            _ownedTokensIndex[tokenId] = 0;
    
            _removeTokenFromAllTokensEnumeration(tokenId);
        }
    
        /**
         * @dev Gets the list of token IDs of the requested owner.
         * @param owner address owning the tokens
         * @return uint256[] List of token IDs owned by the requested address
         */
        function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
            return _ownedTokens[owner];
        }
    
        /**
         * @dev Private function to add a token to this extension's ownership-tracking data structures.
         * @param to address representing the new owner of the given token ID
         * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
         */
        function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
            _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
            _ownedTokens[to].push(tokenId);
        }
    
        /**
         * @dev Private function to add a token to this extension's token tracking data structures.
         * @param tokenId uint256 ID of the token to be added to the tokens list
         */
        function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
            _allTokensIndex[tokenId] = _allTokens.length;
            _allTokens.push(tokenId);
        }
    
        /**
         * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
         * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for
         * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
         * This has O(1) time complexity, but alters the order of the _ownedTokens array.
         * @param from address representing the previous owner of the given token ID
         * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
         */
        function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
            // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
            // then delete the last slot (swap and pop).
    
            uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
            uint256 tokenIndex = _ownedTokensIndex[tokenId];
    
            // When the token to delete is the last token, the swap operation is unnecessary
            if (tokenIndex != lastTokenIndex) {
                uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
    
                _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
                _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
            }
    
            // This also deletes the contents at the last position of the array
            _ownedTokens[from].length--;
    
            // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
            // lastTokenId, or just over the end of the array if the token was the last one).
        }
    
        /**
         * @dev Private function to remove a token from this extension's token tracking data structures.
         * This has O(1) time complexity, but alters the order of the _allTokens array.
         * @param tokenId uint256 ID of the token to be removed from the tokens list
         */
        function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
            // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
            // then delete the last slot (swap and pop).
    
            uint256 lastTokenIndex = _allTokens.length.sub(1);
            uint256 tokenIndex = _allTokensIndex[tokenId];
    
            // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
            // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
            // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
            uint256 lastTokenId = _allTokens[lastTokenIndex];
    
            _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
    
            // This also deletes the contents at the last position of the array
            _allTokens.length--;
            _allTokensIndex[tokenId] = 0;
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract IERC721Metadata is IERC721 {
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function tokenURI(uint256 tokenId) external view returns (string memory);
    }
    
    // File: @openzeppelin/contracts/token/ERC721/ERC721Metadata.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    contract ERC721Metadata is ERC165, ERC721, IERC721Metadata {
        // Token name
        string private _name;
    
        // Token symbol
        string private _symbol;
    
        // Optional mapping for token URIs
        mapping(uint256 => string) private _tokenURIs;
    
        /*
         *     bytes4(keccak256('name()')) == 0x06fdde03
         *     bytes4(keccak256('symbol()')) == 0x95d89b41
         *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
         *
         *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
         */
        bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
    
        /**
         * @dev Constructor function
         */
        constructor (string memory name, string memory symbol) public {
            _name = name;
            _symbol = symbol;
    
            // register the supported interfaces to conform to ERC721 via ERC165
            _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        }
    
        /**
         * @dev Gets the token name.
         * @return string representing the token name
         */
        function name() external view returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Gets the token symbol.
         * @return string representing the token symbol
         */
        function symbol() external view returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns an URI for a given token ID.
         * Throws if the token ID does not exist. May return an empty string.
         * @param tokenId uint256 ID of the token to query
         */
        function tokenURI(uint256 tokenId) external view returns (string memory) {
            require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
            return _tokenURIs[tokenId];
        }
    
        /**
         * @dev Internal function to set the token URI for a given token.
         * Reverts if the token ID does not exist.
         * @param tokenId uint256 ID of the token to set its URI
         * @param uri string URI to assign
         */
        function _setTokenURI(uint256 tokenId, string memory uri) internal {
            require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
            _tokenURIs[tokenId] = uri;
        }
    
        /**
         * @dev Internal function to burn a specific token.
         * Reverts if the token does not exist.
         * Deprecated, use _burn(uint256) instead.
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned by the msg.sender
         */
        function _burn(address owner, uint256 tokenId) internal {
            super._burn(owner, tokenId);
    
            // Clear metadata (if any)
            if (bytes(_tokenURIs[tokenId]).length != 0) {
                delete _tokenURIs[tokenId];
            }
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC721/ERC721Full.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @title Full ERC721 Token
     * This implementation includes all the required and some optional functionality of the ERC721 standard
     * Moreover, it includes approve all functionality using operator terminology
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
        constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) {
            // solhint-disable-previous-line no-empty-blocks
        }
    }
    
    // File: contracts/libs/String.sol
    
    pragma solidity ^0.5.11;
    
    library String {
    
        /**
         * @dev Convert bytes32 to string.
         * @param _x - to be converted to string.
         * @return string
         */
        function bytes32ToString(bytes32 _x) internal pure returns (string memory) {
            bytes memory bytesString = new bytes(32);
            uint charCount = 0;
            for (uint j = 0; j < 32; j++) {
                byte char = byte(bytes32(uint(_x) * 2 ** (8 * j)));
                if (char != 0) {
                    bytesString[charCount] = char;
                    charCount++;
                }
            }
            bytes memory bytesStringTrimmed = new bytes(charCount);
            for (uint j = 0; j < charCount; j++) {
                bytesStringTrimmed[j] = bytesString[j];
            }
            return string(bytesStringTrimmed);
        }
    
        /**
         * @dev Convert uint to string.
         * @param _i - uint256 to be converted to string.
         * @return uint in string
         */
        function uintToString(uint _i) internal pure returns (string memory _uintAsString) {
            uint i = _i;
    
            if (i == 0) {
                return "0";
            }
            uint j = i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while (i != 0) {
                bstr[k--] = byte(uint8(48 + i % 10));
                i /= 10;
            }
            return string(bstr);
        }
    }
    
    // File: contracts/ERC721BaseCollection.sol
    
    pragma solidity ^0.5.11;
    
    
    
    
    contract ERC721BaseCollection is Ownable, ERC721Full {
        using String for bytes32;
        using String for uint256;
    
        mapping(bytes32 => uint256) public maxIssuance;
        mapping(bytes32 => uint) public issued;
        mapping(uint256 => string) internal _tokenPaths;
        mapping(address => bool) public allowed;
    
        string[] public wearables;
    
        string public baseURI;
        bool public isComplete;
    
        event BaseURI(string _oldBaseURI, string _newBaseURI);
        event Allowed(address indexed _operator, bool _allowed);
        event AddWearable(bytes32 indexed _wearableIdKey, string _wearableId, uint256 _maxIssuance);
        event Issue(address indexed _beneficiary, uint256 indexed _tokenId, bytes32 indexed _wearableIdKey, string _wearableId, uint256 _issuedId);
        event Complete();
    
    
        /**
         * @dev Create the contract.
         * @param _name - name of the contract
         * @param _symbol - symbol of the contract
         * @param _operator - Address allowed to mint tokens
         * @param _baseURI - base URI for token URIs
         */
        constructor(string memory _name, string memory _symbol, address _operator, string memory _baseURI) public ERC721Full(_name, _symbol) {
            setAllowed(_operator, true);
            setBaseURI(_baseURI);
        }
    
        modifier onlyAllowed() {
            require(allowed[msg.sender], "Only an `allowed` address can issue tokens");
            _;
        }
    
    
        /**
         * @dev Set Base URI.
         * @param _baseURI - base URI for token URIs
         */
        function setBaseURI(string memory _baseURI) public onlyOwner {
            emit BaseURI(baseURI, _baseURI);
            baseURI = _baseURI;
        }
    
        /**
         * @dev Set allowed account to issue tokens.
         * @param _operator - Address allowed to issue tokens
         * @param _allowed - Whether is allowed or not
         */
        function setAllowed(address _operator, bool _allowed) public onlyOwner {
            require(_operator != address(0), "Invalid address");
            require(allowed[_operator] != _allowed, "You should set a different value");
    
            allowed[_operator] = _allowed;
            emit Allowed(_operator, _allowed);
        }
    
    
        /**
         * @dev Returns an URI for a given token ID.
         * Throws if the token ID does not exist. May return an empty string.
         * @param _tokenId - uint256 ID of the token queried
         * @return token URI
         */
        function tokenURI(uint256 _tokenId) external view returns (string memory) {
            require(_exists(_tokenId), "ERC721Metadata: received a URI query for a nonexistent token");
            return string(abi.encodePacked(baseURI, _tokenPaths[_tokenId]));
        }
    
    
        /**
         * @dev Transfers the ownership of given tokens ID to another address.
         * Usage of this method is discouraged, use {safeBatchTransferFrom} whenever possible.
         * Requires the msg.sender to be the owner, approved, or operator.
         * @param _from current owner of the token
         * @param _to address to receive the ownership of the given token ID
         * @param _tokenIds uint256 ID of the token to be transferred
         */
        function batchTransferFrom(address _from, address _to, uint256[] calldata _tokenIds) external {
            for (uint256 i = 0; i < _tokenIds.length; i++) {
                transferFrom(_from, _to, _tokenIds[i]);
            }
        }
    
        /**
         * @dev Returns the wearables length.
         * @return wearable length
         */
        function wearablesCount() external view returns (uint256) {
            return wearables.length;
        }
    
        /**
         * @dev Complete the collection.
         * @notice that it will only prevent for adding more wearables.
         * The issuance is still allowed.
         */
        function completeCollection() external onlyOwner {
            require(!isComplete, "The collection is already completed");
            isComplete = true;
            emit Complete();
        }
    
         /**
         * @dev Add a new wearable to the collection.
         * @notice that this method should only allow wearableIds less than or equal to 32 bytes
         * @param _wearableIds - wearable ids
         * @param _maxIssuances - total supply for the wearables
         */
        function addWearables(bytes32[] calldata _wearableIds, uint256[] calldata _maxIssuances) external onlyOwner {
            require(_wearableIds.length == _maxIssuances.length, "Parameters should have the same length");
    
            for (uint256 i = 0; i < _wearableIds.length; i++) {
                addWearable(_wearableIds[i].bytes32ToString(), _maxIssuances[i]);
            }
        }
    
        /**
         * @dev Add a new wearable to the collection.
         * @notice that this method allows wearableIds of any size. It should be used
         * if a wearableId is greater than 32 bytes
         * @param _wearableId - wearable id
         * @param _maxIssuance - total supply for the wearable
         */
        function addWearable(string memory _wearableId, uint256 _maxIssuance) public onlyOwner {
            require(!isComplete, "The collection is complete");
            bytes32 key = getWearableKey(_wearableId);
    
            require(maxIssuance[key] == 0, "Can not modify an existing wearable");
            require(_maxIssuance > 0, "Max issuance should be greater than 0");
    
            maxIssuance[key] = _maxIssuance;
            wearables.push(_wearableId);
    
            emit AddWearable(key, _wearableId, _maxIssuance);
        }
    
        /**
         * @dev Safely transfers the ownership of given token IDs to another address
         * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param _from - current owner of the token
         * @param _to - address to receive the ownership of the given token ID
         * @param _tokenIds - uint256 IDs of the tokens to be transferred
         */
        function safeBatchTransferFrom(address _from, address _to, uint256[] memory _tokenIds) public {
            safeBatchTransferFrom(_from, _to, _tokenIds, "");
        }
    
        /**
         * @dev Safely transfers the ownership of given token IDs to another address
         * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param _from - current owner of the token
         * @param _to - address to receive the ownership of the given token ID
         * @param _tokenIds - uint256 ID of the tokens to be transferred
         * @param _data bytes data to send along with a safe transfer check
         */
        function safeBatchTransferFrom(address _from, address _to, uint256[] memory _tokenIds, bytes memory _data) public {
            for (uint256 i = 0; i < _tokenIds.length; i++) {
                safeTransferFrom(_from, _to, _tokenIds[i], _data);
            }
        }
    
        /**
         * @dev Get keccak256 of a wearableId.
         * @param _wearableId - token wearable
         * @return bytes32 keccak256 of the wearableId
         */
        function getWearableKey(string memory _wearableId) public pure returns (bytes32) {
            return keccak256(abi.encodePacked(_wearableId));
        }
    
        /**
         * @dev Mint a new NFT of the specified kind.
         * @notice that will throw if kind has reached its maximum or is invalid
         * @param _beneficiary - owner of the token
         * @param _tokenId - token
         * @param _wearableIdKey - wearable key
         * @param _wearableId - token wearable
         * @param _issuedId - issued id
         */
        function _mint(
            address _beneficiary,
            uint256 _tokenId,
            bytes32 _wearableIdKey,
            string memory _wearableId,
            uint256 _issuedId
        ) internal {
            // Check issuance
            require(
                _issuedId > 0 && _issuedId <= maxIssuance[_wearableIdKey],
                "Invalid issued id"
            );
            require(issued[_wearableIdKey] < maxIssuance[_wearableIdKey], "Option exhausted");
    
            // Mint erc721 token
            super._mint(_beneficiary, _tokenId);
    
            // Increase issuance
            issued[_wearableIdKey] = issued[_wearableIdKey] + 1;
    
            // Log
            emit Issue(_beneficiary, _tokenId, _wearableIdKey, _wearableId, _issuedId);
        }
    }
    
    // File: contracts/ERC721Collection.sol
    
    pragma solidity ^0.5.11;
    
    
    
    
    contract ERC721Collection is Ownable, ERC721Full, ERC721BaseCollection {
        /**
         * @dev Create the contract.
         * @param _name - name of the contract
         * @param _symbol - symbol of the contract
         * @param _operator - Address allowed to mint tokens
         * @param _baseURI - base URI for token URIs
         */
        constructor(
            string memory _name,
            string memory _symbol,
            address _operator,
            string memory _baseURI
        ) public ERC721BaseCollection(_name, _symbol, _operator, _baseURI) {}
    
        /**
         * @dev Issue a new NFT of the specified kind.
         * @notice that will throw if kind has reached its maximum or is invalid
         * @param _beneficiary - owner of the token
         * @param _wearableId - token wearable
         */
        function issueToken(address _beneficiary, string calldata _wearableId) external onlyAllowed {
            _issueToken(_beneficiary, _wearableId);
        }
    
        /**
         * @dev Issue NFTs.
         * @notice that will throw if kind has reached its maximum or is invalid
         * @param _beneficiaries - owner of the tokens
         * @param _wearableIds - token wearables
         */
        function issueTokens(address[] calldata _beneficiaries, bytes32[] calldata _wearableIds) external onlyAllowed {
            require(_beneficiaries.length == _wearableIds.length, "Parameters should have the same length");
    
            for(uint256 i = 0; i < _wearableIds.length; i++) {
                _issueToken(_beneficiaries[i], _wearableIds[i].bytes32ToString());
            }
        }
    
        /**
         * @dev Returns an URI for a given token ID.
         * Throws if the token ID does not exist. May return an empty string.
         * @param _tokenId - uint256 ID of the token queried
         * @return token URI
         */
        function tokenURI(uint256 _tokenId) external view returns (string memory) {
            require(_exists(_tokenId), "ERC721Metadata: received a URI query for a nonexistent token");
            return string(abi.encodePacked(baseURI, _tokenPaths[_tokenId]));
        }
    
        /**
         * @dev Issue a new NFT of the specified kind.
         * @notice that will throw if kind has reached its maximum or is invalid
         * @param _beneficiary - owner of the token
         * @param _wearableId - token wearable
         */
        function _issueToken(address _beneficiary, string memory _wearableId) internal {
            bytes32 key = getWearableKey(_wearableId);
            uint256 issuedId = issued[key] + 1;
            uint256 tokenId = this.totalSupply();
    
            _mint(_beneficiary, tokenId, key, _wearableId, issuedId);
            _setTokenURI(
                tokenId,
                string(abi.encodePacked(_wearableId, "/", issuedId.uintToString()))
            );
        }
    
        /**
         * @dev Internal function to set the token URI for a given token.
         * Reverts if the token ID does not exist.
         * @param _tokenId - uint256 ID of the token to set as its URI
         * @param _uri - string URI to assign
         */
        function _setTokenURI(uint256 _tokenId, string memory _uri) internal {
            _tokenPaths[_tokenId] = _uri;
        }
    }