· 6 years ago · Jun 25, 2019, 04:40 PM
1/**
2 *Submitted for verification at Etherscan.io on 2019-05-16
3*/
4
5/*
6 * Crypto stamp
7 * Digitalphysical collectible postage stamp
8 *
9 * Developed by capacity.at
10 * for post.at
11 */
12
13// File: openzeppelin-solidity/contracts/introspection/IERC165.sol
14
15pragma solidity ^0.5.0;
16
17/**
18 * @title IERC165
19 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
20 */
21interface IERC165 {
22 /**
23 * @notice Query if a contract implements an interface
24 * @param interfaceId The interface identifier, as specified in ERC-165
25 * @dev Interface identification is specified in ERC-165. This function
26 * uses less than 30,000 gas.
27 */
28 function supportsInterface(bytes4 interfaceId) external view returns (bool);
29}
30
31// File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
32
33pragma solidity ^0.5.0;
34
35
36/**
37 * @title ERC721 Non-Fungible Token Standard basic interface
38 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
39 */
40contract IERC721 is IERC165 {
41 event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
42 event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
43 event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
44
45 function balanceOf(address owner) public view returns (uint256 balance);
46 function ownerOf(uint256 tokenId) public view returns (address owner);
47
48 function approve(address to, uint256 tokenId) public;
49 function getApproved(uint256 tokenId) public view returns (address operator);
50
51 function setApprovalForAll(address operator, bool _approved) public;
52 function isApprovedForAll(address owner, address operator) public view returns (bool);
53
54 function transferFrom(address from, address to, uint256 tokenId) public;
55 function safeTransferFrom(address from, address to, uint256 tokenId) public;
56
57 function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
58}
59
60// File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol
61
62pragma solidity ^0.5.0;
63
64/**
65 * @title ERC721 token receiver interface
66 * @dev Interface for any contract that wants to support safeTransfers
67 * from ERC721 asset contracts.
68 */
69contract IERC721Receiver {
70 /**
71 * @notice Handle the receipt of an NFT
72 * @dev The ERC721 smart contract calls this function on the recipient
73 * after a `safeTransfer`. This function MUST return the function selector,
74 * otherwise the caller will revert the transaction. The selector to be
75 * returned can be obtained as `this.onERC721Received.selector`. This
76 * function MAY throw to revert and reject the transfer.
77 * Note: the ERC721 contract address is always the message sender.
78 * @param operator The address which called `safeTransferFrom` function
79 * @param from The address which previously owned the token
80 * @param tokenId The NFT identifier which is being transferred
81 * @param data Additional data with no specified format
82 * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
83 */
84 function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
85 public returns (bytes4);
86}
87
88// File: openzeppelin-solidity/contracts/math/SafeMath.sol
89
90pragma solidity ^0.5.0;
91
92/**
93 * @title SafeMath
94 * @dev Unsigned math operations with safety checks that revert on error
95 */
96library SafeMath {
97 /**
98 * @dev Multiplies two unsigned integers, reverts on overflow.
99 */
100 function mul(uint256 a, uint256 b) internal pure returns (uint256) {
101 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
102 // benefit is lost if 'b' is also tested.
103 // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
104 if (a == 0) {
105 return 0;
106 }
107
108 uint256 c = a * b;
109 require(c / a == b);
110
111 return c;
112 }
113
114 /**
115 * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
116 */
117 function div(uint256 a, uint256 b) internal pure returns (uint256) {
118 // Solidity only automatically asserts when dividing by 0
119 require(b > 0);
120 uint256 c = a / b;
121 // assert(a == b * c + a % b); // There is no case in which this doesn't hold
122
123 return c;
124 }
125
126 /**
127 * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
128 */
129 function sub(uint256 a, uint256 b) internal pure returns (uint256) {
130 require(b <= a);
131 uint256 c = a - b;
132
133 return c;
134 }
135
136 /**
137 * @dev Adds two unsigned integers, reverts on overflow.
138 */
139 function add(uint256 a, uint256 b) internal pure returns (uint256) {
140 uint256 c = a + b;
141 require(c >= a);
142
143 return c;
144 }
145
146 /**
147 * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
148 * reverts when dividing by zero.
149 */
150 function mod(uint256 a, uint256 b) internal pure returns (uint256) {
151 require(b != 0);
152 return a % b;
153 }
154}
155
156// File: openzeppelin-solidity/contracts/utils/Address.sol
157
158pragma solidity ^0.5.0;
159
160/**
161 * Utility library of inline functions on addresses
162 */
163library Address {
164 /**
165 * Returns whether the target address is a contract
166 * @dev This function will return false if invoked during the constructor of a contract,
167 * as the code is not actually created until after the constructor finishes.
168 * @param account address of the account to check
169 * @return whether the target address is a contract
170 */
171 function isContract(address account) internal view returns (bool) {
172 uint256 size;
173 // XXX Currently there is no better way to check if there is a contract in an address
174 // than to check the size of the code at that address.
175 // See https://ethereum.stackexchange.com/a/14016/36603
176 // for more details about how this works.
177 // TODO Check this again before the Serenity release, because all addresses will be
178 // contracts then.
179 // solhint-disable-next-line no-inline-assembly
180 assembly { size := extcodesize(account) }
181 return size > 0;
182 }
183}
184
185// File: openzeppelin-solidity/contracts/introspection/ERC165.sol
186
187pragma solidity ^0.5.0;
188
189
190/**
191 * @title ERC165
192 * @author Matt Condon (@shrugs)
193 * @dev Implements ERC165 using a lookup table.
194 */
195contract ERC165 is IERC165 {
196 bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
197 /**
198 * 0x01ffc9a7 ===
199 * bytes4(keccak256('supportsInterface(bytes4)'))
200 */
201
202 /**
203 * @dev a mapping of interface id to whether or not it's supported
204 */
205 mapping(bytes4 => bool) private _supportedInterfaces;
206
207 /**
208 * @dev A contract implementing SupportsInterfaceWithLookup
209 * implement ERC165 itself
210 */
211 constructor () internal {
212 _registerInterface(_INTERFACE_ID_ERC165);
213 }
214
215 /**
216 * @dev implement supportsInterface(bytes4) using a lookup table
217 */
218 function supportsInterface(bytes4 interfaceId) external view returns (bool) {
219 return _supportedInterfaces[interfaceId];
220 }
221
222 /**
223 * @dev internal method for registering an interface
224 */
225 function _registerInterface(bytes4 interfaceId) internal {
226 require(interfaceId != 0xffffffff);
227 _supportedInterfaces[interfaceId] = true;
228 }
229}
230
231// File: openzeppelin-solidity/contracts/token/ERC721/ERC721.sol
232
233pragma solidity ^0.5.0;
234
235
236
237
238
239
240/**
241 * @title ERC721 Non-Fungible Token Standard basic implementation
242 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
243 */
244contract ERC721 is ERC165, IERC721 {
245 using SafeMath for uint256;
246 using Address for address;
247
248 // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
249 // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
250 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
251
252 // Mapping from token ID to owner
253 mapping (uint256 => address) private _tokenOwner;
254
255 // Mapping from token ID to approved address
256 mapping (uint256 => address) private _tokenApprovals;
257
258 // Mapping from owner to number of owned token
259 mapping (address => uint256) private _ownedTokensCount;
260
261 // Mapping from owner to operator approvals
262 mapping (address => mapping (address => bool)) private _operatorApprovals;
263
264 bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
265 /*
266 * 0x80ac58cd ===
267 * bytes4(keccak256('balanceOf(address)')) ^
268 * bytes4(keccak256('ownerOf(uint256)')) ^
269 * bytes4(keccak256('approve(address,uint256)')) ^
270 * bytes4(keccak256('getApproved(uint256)')) ^
271 * bytes4(keccak256('setApprovalForAll(address,bool)')) ^
272 * bytes4(keccak256('isApprovedForAll(address,address)')) ^
273 * bytes4(keccak256('transferFrom(address,address,uint256)')) ^
274 * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
275 * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
276 */
277
278 constructor () public {
279 // register the supported interfaces to conform to ERC721 via ERC165
280 _registerInterface(_INTERFACE_ID_ERC721);
281 }
282
283 /**
284 * @dev Gets the balance of the specified address
285 * @param owner address to query the balance of
286 * @return uint256 representing the amount owned by the passed address
287 */
288 function balanceOf(address owner) public view returns (uint256) {
289 require(owner != address(0));
290 return _ownedTokensCount[owner];
291 }
292
293 /**
294 * @dev Gets the owner of the specified token ID
295 * @param tokenId uint256 ID of the token to query the owner of
296 * @return owner address currently marked as the owner of the given token ID
297 */
298 function ownerOf(uint256 tokenId) public view returns (address) {
299 address owner = _tokenOwner[tokenId];
300 require(owner != address(0));
301 return owner;
302 }
303
304 /**
305 * @dev Approves another address to transfer the given token ID
306 * The zero address indicates there is no approved address.
307 * There can only be one approved address per token at a given time.
308 * Can only be called by the token owner or an approved operator.
309 * @param to address to be approved for the given token ID
310 * @param tokenId uint256 ID of the token to be approved
311 */
312 function approve(address to, uint256 tokenId) public {
313 address owner = ownerOf(tokenId);
314 require(to != owner);
315 require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
316
317 _tokenApprovals[tokenId] = to;
318 emit Approval(owner, to, tokenId);
319 }
320
321 /**
322 * @dev Gets the approved address for a token ID, or zero if no address set
323 * Reverts if the token ID does not exist.
324 * @param tokenId uint256 ID of the token to query the approval of
325 * @return address currently approved for the given token ID
326 */
327 function getApproved(uint256 tokenId) public view returns (address) {
328 require(_exists(tokenId));
329 return _tokenApprovals[tokenId];
330 }
331
332 /**
333 * @dev Sets or unsets the approval of a given operator
334 * An operator is allowed to transfer all tokens of the sender on their behalf
335 * @param to operator address to set the approval
336 * @param approved representing the status of the approval to be set
337 */
338 function setApprovalForAll(address to, bool approved) public {
339 require(to != msg.sender);
340 _operatorApprovals[msg.sender][to] = approved;
341 emit ApprovalForAll(msg.sender, to, approved);
342 }
343
344 /**
345 * @dev Tells whether an operator is approved by a given owner
346 * @param owner owner address which you want to query the approval of
347 * @param operator operator address which you want to query the approval of
348 * @return bool whether the given operator is approved by the given owner
349 */
350 function isApprovedForAll(address owner, address operator) public view returns (bool) {
351 return _operatorApprovals[owner][operator];
352 }
353
354 /**
355 * @dev Transfers the ownership of a given token ID to another address
356 * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
357 * Requires the msg sender to be the owner, approved, or operator
358 * @param from current owner of the token
359 * @param to address to receive the ownership of the given token ID
360 * @param tokenId uint256 ID of the token to be transferred
361 */
362 function transferFrom(address from, address to, uint256 tokenId) public {
363 require(_isApprovedOrOwner(msg.sender, tokenId));
364
365 _transferFrom(from, to, tokenId);
366 }
367
368 /**
369 * @dev Safely transfers the ownership of a given token ID to another address
370 * If the target address is a contract, it must implement `onERC721Received`,
371 * which is called upon a safe transfer, and return the magic value
372 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
373 * the transfer is reverted.
374 *
375 * Requires the msg sender to be the owner, approved, or operator
376 * @param from current owner of the token
377 * @param to address to receive the ownership of the given token ID
378 * @param tokenId uint256 ID of the token to be transferred
379 */
380 function safeTransferFrom(address from, address to, uint256 tokenId) public {
381 safeTransferFrom(from, to, tokenId, "");
382 }
383
384 /**
385 * @dev Safely transfers the ownership of a given token ID to another address
386 * If the target address is a contract, it must implement `onERC721Received`,
387 * which is called upon a safe transfer, and return the magic value
388 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
389 * the transfer is reverted.
390 * Requires the msg sender to be the owner, approved, or operator
391 * @param from current owner of the token
392 * @param to address to receive the ownership of the given token ID
393 * @param tokenId uint256 ID of the token to be transferred
394 * @param _data bytes data to send along with a safe transfer check
395 */
396 function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
397 transferFrom(from, to, tokenId);
398 require(_checkOnERC721Received(from, to, tokenId, _data));
399 }
400
401 /**
402 * @dev Returns whether the specified token exists
403 * @param tokenId uint256 ID of the token to query the existence of
404 * @return whether the token exists
405 */
406 function _exists(uint256 tokenId) internal view returns (bool) {
407 address owner = _tokenOwner[tokenId];
408 return owner != address(0);
409 }
410
411 /**
412 * @dev Returns whether the given spender can transfer a given token ID
413 * @param spender address of the spender to query
414 * @param tokenId uint256 ID of the token to be transferred
415 * @return bool whether the msg.sender is approved for the given token ID,
416 * is an operator of the owner, or is the owner of the token
417 */
418 function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
419 address owner = ownerOf(tokenId);
420 return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
421 }
422
423 /**
424 * @dev Internal function to mint a new token
425 * Reverts if the given token ID already exists
426 * @param to The address that will own the minted token
427 * @param tokenId uint256 ID of the token to be minted
428 */
429 function _mint(address to, uint256 tokenId) internal {
430 require(to != address(0));
431 require(!_exists(tokenId));
432
433 _tokenOwner[tokenId] = to;
434 _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
435
436 emit Transfer(address(0), to, tokenId);
437 }
438
439 /**
440 * @dev Internal function to burn a specific token
441 * Reverts if the token does not exist
442 * Deprecated, use _burn(uint256) instead.
443 * @param owner owner of the token to burn
444 * @param tokenId uint256 ID of the token being burned
445 */
446 function _burn(address owner, uint256 tokenId) internal {
447 require(ownerOf(tokenId) == owner);
448
449 _clearApproval(tokenId);
450
451 _ownedTokensCount[owner] = _ownedTokensCount[owner].sub(1);
452 _tokenOwner[tokenId] = address(0);
453
454 emit Transfer(owner, address(0), tokenId);
455 }
456
457 /**
458 * @dev Internal function to burn a specific token
459 * Reverts if the token does not exist
460 * @param tokenId uint256 ID of the token being burned
461 */
462 function _burn(uint256 tokenId) internal {
463 _burn(ownerOf(tokenId), tokenId);
464 }
465
466 /**
467 * @dev Internal function to transfer ownership of a given token ID to another address.
468 * As opposed to transferFrom, this imposes no restrictions on msg.sender.
469 * @param from current owner of the token
470 * @param to address to receive the ownership of the given token ID
471 * @param tokenId uint256 ID of the token to be transferred
472 */
473 function _transferFrom(address from, address to, uint256 tokenId) internal {
474 require(ownerOf(tokenId) == from);
475 require(to != address(0));
476
477 _clearApproval(tokenId);
478
479 _ownedTokensCount[from] = _ownedTokensCount[from].sub(1);
480 _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
481
482 _tokenOwner[tokenId] = to;
483
484 emit Transfer(from, to, tokenId);
485 }
486
487 /**
488 * @dev Internal function to invoke `onERC721Received` on a target address
489 * The call is not executed if the target address is not a contract
490 * @param from address representing the previous owner of the given token ID
491 * @param to target address that will receive the tokens
492 * @param tokenId uint256 ID of the token to be transferred
493 * @param _data bytes optional data to send along with the call
494 * @return whether the call correctly returned the expected magic value
495 */
496 function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
497 internal returns (bool)
498 {
499 if (!to.isContract()) {
500 return true;
501 }
502
503 bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
504 return (retval == _ERC721_RECEIVED);
505 }
506
507 /**
508 * @dev Private function to clear current approval of a given token ID
509 * @param tokenId uint256 ID of the token to be transferred
510 */
511 function _clearApproval(uint256 tokenId) private {
512 if (_tokenApprovals[tokenId] != address(0)) {
513 _tokenApprovals[tokenId] = address(0);
514 }
515 }
516}
517
518// File: openzeppelin-solidity/contracts/token/ERC721/IERC721Enumerable.sol
519
520pragma solidity ^0.5.0;
521
522
523/**
524 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
525 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
526 */
527contract IERC721Enumerable is IERC721 {
528 function totalSupply() public view returns (uint256);
529 function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);
530
531 function tokenByIndex(uint256 index) public view returns (uint256);
532}
533
534// File: contracts/ERC721EnumerableSimple.sol
535
536pragma solidity ^0.5.0;
537
538/* This is a simplified (and cheaper) version of OpenZeppelin's ERC721Enumerable.
539 * ERC721Enumerable's allTokens array and allTokensIndex mapping are eliminated.
540 * Side effects: _burn cannot be used any more with this, and creation needs to be
541 * in ascending order, starting with 0, and have no holes in the sequence of IDs.
542 */
543
544
545
546
547/**
548 * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
549 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
550 */
551contract ERC721EnumerableSimple is ERC165, ERC721, IERC721Enumerable {
552 // Mapping from owner to list of owned token IDs
553 mapping(address => uint256[]) private _ownedTokens;
554
555 // Mapping from token ID to index of the owner tokens list
556 mapping(uint256 => uint256) private _ownedTokensIndex;
557
558 uint256 internal totalSupply_;
559
560 bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
561 /**
562 * 0x780e9d63 ===
563 * bytes4(keccak256('totalSupply()')) ^
564 * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
565 * bytes4(keccak256('tokenByIndex(uint256)'))
566 */
567
568 /**
569 * @dev Constructor function
570 */
571 constructor () public {
572 // register the supported interface to conform to ERC721 via ERC165
573 _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
574 }
575
576 /**
577 * @dev Gets the token ID at a given index of the tokens list of the requested owner
578 * @param owner address owning the tokens list to be accessed
579 * @param index uint256 representing the index to be accessed of the requested tokens list
580 * @return uint256 token ID at the given index of the tokens list owned by the requested address
581 */
582 function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
583 require(index < balanceOf(owner), "Index is higher than number of tokens owned.");
584 return _ownedTokens[owner][index];
585 }
586
587 /**
588 * @dev Gets the total amount of tokens stored by the contract
589 * @return uint256 representing the total amount of tokens
590 */
591 function totalSupply() public view returns (uint256) {
592 return totalSupply_;
593 }
594
595
596 /**
597 * @dev Gets the token ID at a given index of all the tokens in this contract
598 * Reverts if the index is greater or equal to the total number of tokens
599 * @param index uint256 representing the index to be accessed of the tokens list
600 * @return uint256 token ID at the given index of the tokens list
601 */
602 function tokenByIndex(uint256 index) public view returns (uint256) {
603 require(index < totalSupply(), "Index is out of bounds.");
604 return index;
605 }
606
607
608 /**
609 * @dev Internal function to transfer ownership of a given token ID to another address.
610 * As opposed to transferFrom, this imposes no restrictions on msg.sender.
611 * @param from current owner of the token
612 * @param to address to receive the ownership of the given token ID
613 * @param tokenId uint256 ID of the token to be transferred
614 */
615 function _transferFrom(address from, address to, uint256 tokenId) internal {
616 super._transferFrom(from, to, tokenId);
617
618 _removeTokenFromOwnerEnumeration(from, tokenId);
619
620 _addTokenToOwnerEnumeration(to, tokenId);
621 }
622
623 /**
624 * @dev Internal function to mint a new token
625 * Reverts if the given token ID already exists
626 * @param to address the beneficiary that will own the minted token
627 * @param tokenId uint256 ID of the token to be minted
628 */
629 function _mint(address to, uint256 tokenId) internal {
630 super._mint(to, tokenId);
631
632 _addTokenToOwnerEnumeration(to, tokenId);
633
634 totalSupply_ = totalSupply_.add(1);
635 }
636
637 /**
638 * @dev Internal function to burn a specific token
639 * Reverts if the token does not exist
640 * Deprecated, use _burn(uint256) instead
641 * param owner owner of the token to burn
642 * param tokenId uint256 ID of the token being burned
643 */
644 function _burn(address /*owner*/, uint256 /*tokenId*/) internal {
645 revert("This token cannot be burned.");
646 }
647
648 /**
649 * @dev Gets the list of token IDs of the requested owner
650 * @param owner address owning the tokens
651 * @return uint256[] List of token IDs owned by the requested address
652 */
653 function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
654 return _ownedTokens[owner];
655 }
656
657 /**
658 * @dev Private function to add a token to this extension's ownership-tracking data structures.
659 * @param to address representing the new owner of the given token ID
660 * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
661 */
662 function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
663 _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
664 _ownedTokens[to].push(tokenId);
665 }
666
667 /**
668 * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
669 * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for
670 * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
671 * This has O(1) time complexity, but alters the order of the _ownedTokens array.
672 * @param from address representing the previous owner of the given token ID
673 * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
674 */
675 function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
676 // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
677 // then delete the last slot (swap and pop).
678
679 uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
680 uint256 tokenIndex = _ownedTokensIndex[tokenId];
681
682 // When the token to delete is the last token, the swap operation is unnecessary
683 if (tokenIndex != lastTokenIndex) {
684 uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
685
686 _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
687 _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
688 }
689
690 // This also deletes the contents at the last position of the array
691 _ownedTokens[from].length--;
692
693 // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occcupied by
694 // lasTokenId, or just over the end of the array if the token was the last one).
695 }
696}
697
698// File: openzeppelin-solidity/contracts/token/ERC721/IERC721Metadata.sol
699
700pragma solidity ^0.5.0;
701
702
703/**
704 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
705 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
706 */
707contract IERC721Metadata is IERC721 {
708 function name() external view returns (string memory);
709 function symbol() external view returns (string memory);
710 function tokenURI(uint256 tokenId) external view returns (string memory);
711}
712
713// File: openzeppelin-solidity/contracts/token/ERC721/ERC721Metadata.sol
714
715pragma solidity ^0.5.0;
716
717
718
719
720contract ERC721Metadata is ERC165, ERC721, IERC721Metadata {
721 // Token name
722 string private _name;
723
724 // Token symbol
725 string private _symbol;
726
727 // Optional mapping for token URIs
728 mapping(uint256 => string) private _tokenURIs;
729
730 bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
731 /**
732 * 0x5b5e139f ===
733 * bytes4(keccak256('name()')) ^
734 * bytes4(keccak256('symbol()')) ^
735 * bytes4(keccak256('tokenURI(uint256)'))
736 */
737
738 /**
739 * @dev Constructor function
740 */
741 constructor (string memory name, string memory symbol) public {
742 _name = name;
743 _symbol = symbol;
744
745 // register the supported interfaces to conform to ERC721 via ERC165
746 _registerInterface(_INTERFACE_ID_ERC721_METADATA);
747 }
748
749 /**
750 * @dev Gets the token name
751 * @return string representing the token name
752 */
753 function name() external view returns (string memory) {
754 return _name;
755 }
756
757 /**
758 * @dev Gets the token symbol
759 * @return string representing the token symbol
760 */
761 function symbol() external view returns (string memory) {
762 return _symbol;
763 }
764
765 /**
766 * @dev Returns an URI for a given token ID
767 * Throws if the token ID does not exist. May return an empty string.
768 * @param tokenId uint256 ID of the token to query
769 */
770 function tokenURI(uint256 tokenId) external view returns (string memory) {
771 require(_exists(tokenId));
772 return _tokenURIs[tokenId];
773 }
774
775 /**
776 * @dev Internal function to set the token URI for a given token
777 * Reverts if the token ID does not exist
778 * @param tokenId uint256 ID of the token to set its URI
779 * @param uri string URI to assign
780 */
781 function _setTokenURI(uint256 tokenId, string memory uri) internal {
782 require(_exists(tokenId));
783 _tokenURIs[tokenId] = uri;
784 }
785
786 /**
787 * @dev Internal function to burn a specific token
788 * Reverts if the token does not exist
789 * Deprecated, use _burn(uint256) instead
790 * @param owner owner of the token to burn
791 * @param tokenId uint256 ID of the token being burned by the msg.sender
792 */
793 function _burn(address owner, uint256 tokenId) internal {
794 super._burn(owner, tokenId);
795
796 // Clear metadata (if any)
797 if (bytes(_tokenURIs[tokenId]).length != 0) {
798 delete _tokenURIs[tokenId];
799 }
800 }
801}
802
803// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
804
805pragma solidity ^0.5.0;
806
807/**
808 * @title ERC20 interface
809 * @dev see https://github.com/ethereum/EIPs/issues/20
810 */
811interface IERC20 {
812 function transfer(address to, uint256 value) external returns (bool);
813
814 function approve(address spender, uint256 value) external returns (bool);
815
816 function transferFrom(address from, address to, uint256 value) external returns (bool);
817
818 function totalSupply() external view returns (uint256);
819
820 function balanceOf(address who) external view returns (uint256);
821
822 function allowance(address owner, address spender) external view returns (uint256);
823
824 event Transfer(address indexed from, address indexed to, uint256 value);
825
826 event Approval(address indexed owner, address indexed spender, uint256 value);
827}
828
829// File: contracts/Cryptostamp.sol
830
831/*
832Implements ERC 721 Token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
833*/
834pragma solidity ^0.5.0;
835
836
837
838
839
840/* The inheritance is very much the same as OpenZeppelin's ERC721Full,
841 * but using a simplified (and cheaper) version of ERC721Enumerable */
842contract Cryptostamp is ERC721, ERC721EnumerableSimple, ERC721Metadata("Crypto stamp Edition 1", "CS1") {
843
844 string public uribase;
845
846 address public createControl;
847
848 address public tokenAssignmentControl;
849
850 bool public mintingFinished = false;
851
852 constructor(address _createControl, address _tokenAssignmentControl)
853 public
854 {
855 createControl = _createControl;
856 tokenAssignmentControl = _tokenAssignmentControl;
857 uribase = "https://test.crypto.post.at/CS1/meta/";
858 }
859
860 modifier onlyCreateControl()
861 {
862 require(msg.sender == createControl, "createControl key required for this function.");
863 _;
864 }
865
866 modifier onlyTokenAssignmentControl() {
867 require(msg.sender == tokenAssignmentControl, "tokenAssignmentControl key required for this function.");
868 _;
869 }
870
871 modifier requireMinting() {
872 require(mintingFinished == false, "This call only works when minting is not finished.");
873 _;
874 }
875
876 // Issue a new crypto stamp asset, giving it to a specific owner address.
877 // As appending the ID into a URI in Solidity is complicated, generate both
878 // externally and hand them over to the asset here.
879 function create(uint256 _tokenId, address _owner)
880 public
881 onlyCreateControl
882 requireMinting
883 {
884 // Make sure we do not get any holes in Ids so we can do more optimizations.
885 require(_tokenId == 0 || _exists(_tokenId.sub(1)), "Previous token ID has to exist.");
886 // _mint already ends up checking if owner != 0 and that tokenId doesn't exist yet.
887 _mint(_owner, _tokenId);
888 }
889
890 // Batch-issue multiple crypto stamp with adjacent IDs.
891 function createMulti(uint256 _tokenIdStart, address[] memory _owners)
892 public
893 onlyCreateControl
894 requireMinting
895 {
896 // Make sure we do not get any holes in Ids so we can do more optimizations.
897 require(_tokenIdStart == 0 || _exists(_tokenIdStart.sub(1)), "Previous token ID has to exist.");
898 uint256 addrcount = _owners.length;
899 for (uint256 i = 0; i < addrcount; i++) {
900 // Make sure this is in sync with what create() does.
901 _mint(_owners[i], _tokenIdStart + i);
902 }
903 }
904
905 // Finish the creation/minting process.
906 function finishMinting()
907 public
908 onlyCreateControl
909 {
910 mintingFinished = true;
911 }
912
913 // Set new base for the token URI.
914 function newUriBase(string memory _newUriBase)
915 public
916 onlyCreateControl
917 {
918 uribase = _newUriBase;
919 }
920
921 // Override ERC721Metadata to create the URI from the base and ID.
922 function tokenURI(uint256 _tokenId)
923 external view
924 returns (string memory)
925 {
926 require(_exists(_tokenId), "Token ID does not exist.");
927 return string(abi.encodePacked(uribase, uint2str(_tokenId)));
928 }
929
930 // Returns whether the specified token exists
931 function exists(uint256 tokenId) public view returns (bool) {
932 return _exists(tokenId);
933 }
934
935 // Helper function from Oraclize
936 // https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol
937 function uint2str(uint256 inp)
938 internal pure
939 returns (string memory)
940 {
941 if (inp == 0) return "0";
942 uint i = inp;
943 uint j = i;
944 uint length;
945 while (j != 0){
946 length++;
947 j /= 10;
948 }
949 bytes memory bstr = new bytes(length);
950 uint k = length - 1;
951 while (i != 0){
952 bstr[k--] = byte(uint8(48 + i % 10));
953 i /= 10;
954 }
955 return string(bstr);
956 }
957
958 /*** Make sure currency doesn't get stranded in this contract ***/
959
960 // If this contract gets a balance in some ERC20 contract after it's finished, then we can rescue it.
961 function rescueToken(IERC20 _foreignToken, address _to)
962 external
963 onlyTokenAssignmentControl
964 {
965 _foreignToken.transfer(_to, _foreignToken.balanceOf(address(this)));
966 }
967
968 // Make sure this contract cannot receive ETH.
969 function()
970 external payable
971 {
972 revert("The contract cannot receive ETH payments.");
973 }
974}