Advertisement
Guest User

Untitled

a guest
Jun 25th, 2019
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.59 KB | None | 0 0
  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.  
  15. pragma solidity ^0.5.0;
  16.  
  17. /**
  18. * @title IERC165
  19. * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
  20. */
  21. interface 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.  
  33. pragma 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. */
  40. contract 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.  
  62. pragma 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. */
  69. contract 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.  
  90. pragma solidity ^0.5.0;
  91.  
  92. /**
  93. * @title SafeMath
  94. * @dev Unsigned math operations with safety checks that revert on error
  95. */
  96. library 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.  
  158. pragma solidity ^0.5.0;
  159.  
  160. /**
  161. * Utility library of inline functions on addresses
  162. */
  163. library 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.  
  187. pragma solidity ^0.5.0;
  188.  
  189.  
  190. /**
  191. * @title ERC165
  192. * @author Matt Condon (@shrugs)
  193. * @dev Implements ERC165 using a lookup table.
  194. */
  195. contract 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.  
  233. pragma 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. */
  244. contract 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.  
  520. pragma 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. */
  527. contract 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.  
  536. pragma 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. */
  551. contract 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.  
  700. pragma 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. */
  707. contract 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.  
  715. pragma solidity ^0.5.0;
  716.  
  717.  
  718.  
  719.  
  720. contract 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.  
  805. pragma solidity ^0.5.0;
  806.  
  807. /**
  808. * @title ERC20 interface
  809. * @dev see https://github.com/ethereum/EIPs/issues/20
  810. */
  811. interface 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. /*
  832. Implements ERC 721 Token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
  833. */
  834. pragma 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 */
  842. contract 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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement