Guest User

Untitled

a guest
Jun 23rd, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.24 KB | None | 0 0
  1. pragma solidity ^0.4.22;
  2.  
  3. import './ERC721.sol';
  4. import "./ERC721Receiver.sol";
  5. import "./SafeMath.sol";
  6. import "./AddressUtils.sol";
  7.  
  8. contract Cryptogiphy is ERC721 {
  9. using SafeMath for uint256;
  10. using AddressUtils for address;
  11.  
  12. string public constant name = "Cryptogiphy";
  13. string public constant symbol = "CGIF";
  14.  
  15. // Giphs as tokens that can be owned and transferred
  16. struct Giphtoken {
  17. string name;
  18. string url;
  19. }
  20.  
  21. // Storage for giphs
  22. Giphtoken[] public giphtokens;
  23.  
  24. address public owner;
  25.  
  26. // Maps giphtoken IDs to owners
  27. mapping (uint256 => address) public giphyIndexToOwner;
  28.  
  29. // Maps owners to number of owned giphtokens
  30. mapping (address => uint256) ownershipGiphyCount;
  31.  
  32. // Maps giphtoken IDs to approved addresses
  33. mapping (uint256 => address) public giphyIndexToApproved;
  34.  
  35. // Maps owners to operator approvals
  36. mapping (address => mapping (address => bool)) internal operatorApprovals;
  37.  
  38. // Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
  39. // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
  40. bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;
  41.  
  42.  
  43. /**
  44. * @dev Guarantees msg.sender is owner of the given giphtoken
  45. * @param _tokenId uint256 ID of the giphtoken to validate its ownership belongs to msg.sender
  46. */
  47. modifier onlyOwnerOf(uint256 _tokenId) {
  48. require(ownerOf(_tokenId) == msg.sender);
  49. _;
  50. }
  51.  
  52. /**
  53. * @dev Checks msg.sender can transfer a giphtoken, by being owner, approved, or operator
  54. * @param _tokenId uint256 ID of the giphtoken to validate
  55. */
  56. modifier canTransfer(uint256 _tokenId) {
  57. require(isApprovedOrOwner(msg.sender, _tokenId));
  58. _;
  59. }
  60.  
  61. /**
  62. * @dev Gets the total number of giphtokens currently in existence
  63. * @return uint256 representing the total supply of giphtokens
  64. */
  65. function totalSupply() public view returns (uint256) {
  66. return giphtokens.length;
  67. }
  68.  
  69. /**
  70. * @dev Gets the balance of the specified address
  71. * @param _owner address to query the balance of
  72. * @return uint256 representing the amount owned by the passed address
  73. */
  74. function balanceOf(address _owner) public view returns (uint256) {
  75. require(_owner != address(0));
  76. return ownershipGiphyCount[_owner];
  77. }
  78.  
  79. /**
  80. * @dev Gets the owner of the specified giphtoken ID
  81. * @param _tokenId uint256 ID of the giphtoken to query the owner of
  82. * @return owner address currently marked as the owner of the given giphtoken ID
  83. */
  84. function ownerOf(uint256 _tokenId) public view returns (address) {
  85. address giphyOwner = giphyIndexToOwner[_tokenId];
  86. require(giphyOwner != address(0));
  87. return giphyOwner;
  88. }
  89.  
  90. /**
  91. * @dev Returns whether the specified giphtoken exists
  92. * @param _tokenId uint256 ID of the giphtoken to query the existence of
  93. * @return whether the giphtoken exists
  94. */
  95. function exists(uint256 _tokenId) public view returns (bool) {
  96. address giphyOwner = giphyIndexToOwner[_tokenId];
  97. return giphyOwner != address(0);
  98. }
  99.  
  100. /**
  101. * @dev Approves another address to transfer the given giphtoken ID
  102. * The zero address indicates there is no approved address.
  103. * There can only be one approved address per giphtoken at a given time.
  104. * Can only be called by the giphtoken owner or an approved operator.
  105. * @param _to address to be approved for the given giphtoken ID
  106. * @param _tokenId uint256 ID of the giphtoken to be approved
  107. */
  108. function approve(address _to, uint256 _tokenId) public {
  109. address giphyOwner = ownerOf(_tokenId);
  110. require(_to != giphyOwner);
  111. require(msg.sender == giphyOwner || isApprovedForAll(giphyOwner, msg.sender));
  112.  
  113. giphyIndexToApproved[_tokenId] = _to;
  114. emit Approval(giphyOwner, _to, _tokenId);
  115. }
  116.  
  117. /**
  118. * @dev Gets the approved address for a giphtoken ID, or zero if no address set
  119. * @param _tokenId uint256 ID of the giphtoken to query the approval of
  120. * @return address currently approved for the given giphtoken ID
  121. */
  122. function getApproved(uint256 _tokenId) public view returns (address) {
  123. return giphyIndexToApproved[_tokenId];
  124. }
  125.  
  126. /**
  127. * @dev Sets or unsets the approval of a given operator
  128. * An operator is allowed to transfer all tokens of the sender on their behalf
  129. * @param _to operator address to set the approval
  130. * @param _approved representing the status of the approval to be set
  131. */
  132. function setApprovalForAll(address _to, bool _approved) public {
  133. require(_to != msg.sender);
  134. operatorApprovals[msg.sender][_to] = _approved;
  135. emit ApprovalForAll(msg.sender, _to, _approved);
  136. }
  137.  
  138. /**
  139. * @dev Tells whether an operator is approved by a given owner
  140. * @param _owner owner address which you want to query the approval of
  141. * @param _operator operator address which you want to query the approval of
  142. * @return bool whether the given operator is approved by the given owner
  143. */
  144. function isApprovedForAll(
  145. address _owner,
  146. address _operator
  147. )
  148. public
  149. view
  150. returns (bool)
  151. {
  152. return operatorApprovals[_owner][_operator];
  153. }
  154.  
  155. /**
  156. * @dev Transfers the ownership of a given giphtoken ID to another address
  157. * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
  158. * Requires the msg sender to be the owner, approved, or operator
  159. * @param _from current owner of the giphtoken
  160. * @param _to address to receive the ownership of the given giphtoken ID
  161. * @param _tokenId uint256 ID of the giphtoken to be transferred
  162. */
  163. function transferFrom(
  164. address _from,
  165. address _to,
  166. uint256 _tokenId
  167. )
  168. public
  169. canTransfer(_tokenId)
  170. {
  171. require(_from != address(0));
  172. require(_to != address(0));
  173.  
  174. clearApproval(_from, _tokenId);
  175. removeTokenFrom(_from, _tokenId);
  176. addTokenTo(_to, _tokenId);
  177.  
  178. emit Transfer(_from, _to, _tokenId);
  179. }
  180.  
  181. /**
  182. * @dev Safely transfers the ownership of a given giphtoken ID to another address
  183. * If the target address is a contract, it must implement `onERC721Received`,
  184. * which is called upon a safe transfer, and return the magic value
  185. * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
  186. * the transfer is reverted.
  187. *
  188. * Requires the msg sender to be the owner, approved, or operator
  189. * @param _from current owner of the giphtoken
  190. * @param _to address to receive the ownership of the given giphtoken ID
  191. * @param _tokenId uint256 ID of the giphtoken to be transferred
  192. */
  193. function safeTransferFrom(
  194. address _from,
  195. address _to,
  196. uint256 _tokenId
  197. )
  198. public
  199. canTransfer(_tokenId)
  200. {
  201. safeTransferFrom(_from, _to, _tokenId, "");
  202. }
  203.  
  204. /**
  205. * @dev Safely transfers the ownership of a given giphtoken ID to another address
  206. * If the target address is a contract, it must implement `onERC721Received`,
  207. * which is called upon a safe transfer, and return the magic value
  208. * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
  209. * the transfer is reverted.
  210. * Requires the msg sender to be the owner, approved, or operator
  211. * @param _from current owner of the giphtoken
  212. * @param _to address to receive the ownership of the given giphtoken ID
  213. * @param _tokenId uint256 ID of the giphtoken to be transferred
  214. * @param _data bytes data to send along with a safe transfer check
  215. */
  216. function safeTransferFrom(
  217. address _from,
  218. address _to,
  219. uint256 _tokenId,
  220. bytes _data
  221. )
  222. public
  223. canTransfer(_tokenId)
  224. {
  225. transferFrom(_from, _to, _tokenId);
  226. require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
  227. }
  228.  
  229. /**
  230. * @dev Returns whether the given spender can transfer a given giphtoken ID
  231. * @param _spender address of the spender to query
  232. * @param _tokenId uint256 ID of the giphtoken to be transferred
  233. * @return bool whether the msg.sender is approved for the given giphtoken ID,
  234. * is an operator of the owner, or is the owner of the giphtoken
  235. */
  236. function isApprovedOrOwner(
  237. address _spender,
  238. uint256 _tokenId
  239. )
  240. internal
  241. view
  242. returns (bool)
  243. {
  244. address giphyOwner = ownerOf(_tokenId);
  245. return (
  246. _spender == giphyOwner ||
  247. getApproved(_tokenId) == _spender ||
  248. isApprovedForAll(owner, _spender)
  249. );
  250. }
  251.  
  252. /**
  253. * @dev Internal function to mint a new giphtoken
  254. * Reverts if the given giphtoken ID already exists
  255. * @param _to The address that will own the minted giphtoken
  256. * @param _tokenId uint256 ID of the giphtoken to be minted by the msg.sender
  257. */
  258. function _mint(address _to, uint256 _tokenId) internal {
  259. require(_to != address(0));
  260. addTokenTo(_to, _tokenId);
  261. emit Transfer(address(0), _to, _tokenId);
  262. }
  263.  
  264. /**
  265. * @dev Internal function to clear current approval of a given giphtoken ID
  266. * Reverts if the given address is not indeed the owner of the giphtoken
  267. * @param _owner owner of the giphtoken
  268. * @param _tokenId uint256 ID of the giphtoken to be transferred
  269. */
  270. function clearApproval(address _owner, uint256 _tokenId) internal {
  271. require(ownerOf(_tokenId) == _owner);
  272. if (giphyIndexToApproved[_tokenId] != address(0)) {
  273. giphyIndexToApproved[_tokenId] = address(0);
  274. emit Approval(_owner, address(0), _tokenId);
  275. }
  276. }
  277.  
  278. /**
  279. * @dev Internal function to add a giphtoken ID to the list of a given address
  280. * @param _to address representing the new owner of the given giphtoken ID
  281. * @param _tokenId uint256 ID of the giphtoken to be added to the giphtokens list of the given address
  282. */
  283. function addTokenTo(address _to, uint256 _tokenId) internal {
  284. require(giphyIndexToOwner[_tokenId] == address(0));
  285. giphyIndexToOwner[_tokenId] = _to;
  286. ownershipGiphyCount[_to] = ownershipGiphyCount[_to].add(1);
  287. }
  288.  
  289. /**
  290. * @dev Internal function to remove a giphtoken ID from the list of a given address
  291. * @param _from address representing the previous owner of the given giphtoken ID
  292. * @param _tokenId uint256 ID of the giphtoken to be removed from the tokens list of the given address
  293. */
  294. function removeTokenFrom(address _from, uint256 _tokenId) internal {
  295. require(ownerOf(_tokenId) == _from);
  296. ownershipGiphyCount[_from] = ownershipGiphyCount[_from].sub(1);
  297. giphyIndexToOwner[_tokenId] = address(0);
  298. }
  299.  
  300. /**
  301. * @dev Internal function to invoke `onERC721Received` on a target address
  302. * The call is not executed if the target address is not a contract
  303. * @param _from address representing the previous owner of the given giphtoken ID
  304. * @param _to target address that will receive the giphtokens
  305. * @param _tokenId uint256 ID of the giphtoken to be transferred
  306. * @param _data bytes optional data to send along with the call
  307. * @return whether the call correctly returned the expected magic value
  308. */
  309. function checkAndCallSafeTransfer(
  310. address _from,
  311. address _to,
  312. uint256 _tokenId,
  313. bytes _data
  314. )
  315. internal
  316. returns (bool)
  317. {
  318. if (!_to.isContract()) {
  319. return true;
  320. }
  321. bytes4 retval = ERC721Receiver(_to).onERC721Received(
  322. _from, _tokenId, _data);
  323. return (retval == ERC721_RECEIVED);
  324. }
  325.  
  326. function createGiphtoken(string _name, string _url) public {
  327. uint id = giphtokens.length;
  328. giphtokens.push(Giphtoken(_name, _url));
  329. _mint(msg.sender, id);
  330. }
  331.  
  332. function getMostRecentGiphtoken() public constant returns (string, string) {
  333. return (giphtokens[giphtokens.length].name, giphtokens[giphtokens.length].url);
  334. }
  335.  
  336. }
Add Comment
Please, Sign In to add comment