Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.22;
- import './ERC721.sol';
- import "./ERC721Receiver.sol";
- import "./SafeMath.sol";
- import "./AddressUtils.sol";
- contract Cryptogiphy is ERC721 {
- using SafeMath for uint256;
- using AddressUtils for address;
- string public constant name = "Cryptogiphy";
- string public constant symbol = "CGIF";
- // Giphs as tokens that can be owned and transferred
- struct Giphtoken {
- string name;
- string url;
- }
- // Storage for giphs
- Giphtoken[] public giphtokens;
- address public owner;
- // Maps giphtoken IDs to owners
- mapping (uint256 => address) public giphyIndexToOwner;
- // Maps owners to number of owned giphtokens
- mapping (address => uint256) ownershipGiphyCount;
- // Maps giphtoken IDs to approved addresses
- mapping (uint256 => address) public giphyIndexToApproved;
- // Maps owners to operator approvals
- mapping (address => mapping (address => bool)) internal operatorApprovals;
- // Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
- // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
- bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;
- /**
- * @dev Guarantees msg.sender is owner of the given giphtoken
- * @param _tokenId uint256 ID of the giphtoken to validate its ownership belongs to msg.sender
- */
- modifier onlyOwnerOf(uint256 _tokenId) {
- require(ownerOf(_tokenId) == msg.sender);
- _;
- }
- /**
- * @dev Checks msg.sender can transfer a giphtoken, by being owner, approved, or operator
- * @param _tokenId uint256 ID of the giphtoken to validate
- */
- modifier canTransfer(uint256 _tokenId) {
- require(isApprovedOrOwner(msg.sender, _tokenId));
- _;
- }
- /**
- * @dev Gets the total number of giphtokens currently in existence
- * @return uint256 representing the total supply of giphtokens
- */
- function totalSupply() public view returns (uint256) {
- return giphtokens.length;
- }
- /**
- * @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));
- return ownershipGiphyCount[_owner];
- }
- /**
- * @dev Gets the owner of the specified giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to query the owner of
- * @return owner address currently marked as the owner of the given giphtoken ID
- */
- function ownerOf(uint256 _tokenId) public view returns (address) {
- address giphyOwner = giphyIndexToOwner[_tokenId];
- require(giphyOwner != address(0));
- return giphyOwner;
- }
- /**
- * @dev Returns whether the specified giphtoken exists
- * @param _tokenId uint256 ID of the giphtoken to query the existence of
- * @return whether the giphtoken exists
- */
- function exists(uint256 _tokenId) public view returns (bool) {
- address giphyOwner = giphyIndexToOwner[_tokenId];
- return giphyOwner != address(0);
- }
- /**
- * @dev Approves another address to transfer the given giphtoken ID
- * The zero address indicates there is no approved address.
- * There can only be one approved address per giphtoken at a given time.
- * Can only be called by the giphtoken owner or an approved operator.
- * @param _to address to be approved for the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be approved
- */
- function approve(address _to, uint256 _tokenId) public {
- address giphyOwner = ownerOf(_tokenId);
- require(_to != giphyOwner);
- require(msg.sender == giphyOwner || isApprovedForAll(giphyOwner, msg.sender));
- giphyIndexToApproved[_tokenId] = _to;
- emit Approval(giphyOwner, _to, _tokenId);
- }
- /**
- * @dev Gets the approved address for a giphtoken ID, or zero if no address set
- * @param _tokenId uint256 ID of the giphtoken to query the approval of
- * @return address currently approved for the given giphtoken ID
- */
- function getApproved(uint256 _tokenId) public view returns (address) {
- return giphyIndexToApproved[_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);
- 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 giphtoken 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 giphtoken
- * @param _to address to receive the ownership of the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- */
- function transferFrom(
- address _from,
- address _to,
- uint256 _tokenId
- )
- public
- canTransfer(_tokenId)
- {
- require(_from != address(0));
- require(_to != address(0));
- clearApproval(_from, _tokenId);
- removeTokenFrom(_from, _tokenId);
- addTokenTo(_to, _tokenId);
- emit Transfer(_from, _to, _tokenId);
- }
- /**
- * @dev Safely transfers the ownership of a given giphtoken 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,uint256,bytes)"))`; otherwise,
- * the transfer is reverted.
- *
- * Requires the msg sender to be the owner, approved, or operator
- * @param _from current owner of the giphtoken
- * @param _to address to receive the ownership of the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- */
- function safeTransferFrom(
- address _from,
- address _to,
- uint256 _tokenId
- )
- public
- canTransfer(_tokenId)
- {
- safeTransferFrom(_from, _to, _tokenId, "");
- }
- /**
- * @dev Safely transfers the ownership of a given giphtoken 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,uint256,bytes)"))`; otherwise,
- * the transfer is reverted.
- * Requires the msg sender to be the owner, approved, or operator
- * @param _from current owner of the giphtoken
- * @param _to address to receive the ownership of the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- * @param _data bytes data to send along with a safe transfer check
- */
- function safeTransferFrom(
- address _from,
- address _to,
- uint256 _tokenId,
- bytes _data
- )
- public
- canTransfer(_tokenId)
- {
- transferFrom(_from, _to, _tokenId);
- require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
- }
- /**
- * @dev Returns whether the given spender can transfer a given giphtoken ID
- * @param _spender address of the spender to query
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- * @return bool whether the msg.sender is approved for the given giphtoken ID,
- * is an operator of the owner, or is the owner of the giphtoken
- */
- function isApprovedOrOwner(
- address _spender,
- uint256 _tokenId
- )
- internal
- view
- returns (bool)
- {
- address giphyOwner = ownerOf(_tokenId);
- return (
- _spender == giphyOwner ||
- getApproved(_tokenId) == _spender ||
- isApprovedForAll(owner, _spender)
- );
- }
- /**
- * @dev Internal function to mint a new giphtoken
- * Reverts if the given giphtoken ID already exists
- * @param _to The address that will own the minted giphtoken
- * @param _tokenId uint256 ID of the giphtoken to be minted by the msg.sender
- */
- function _mint(address _to, uint256 _tokenId) internal {
- require(_to != address(0));
- addTokenTo(_to, _tokenId);
- emit Transfer(address(0), _to, _tokenId);
- }
- /**
- * @dev Internal function to clear current approval of a given giphtoken ID
- * Reverts if the given address is not indeed the owner of the giphtoken
- * @param _owner owner of the giphtoken
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- */
- function clearApproval(address _owner, uint256 _tokenId) internal {
- require(ownerOf(_tokenId) == _owner);
- if (giphyIndexToApproved[_tokenId] != address(0)) {
- giphyIndexToApproved[_tokenId] = address(0);
- emit Approval(_owner, address(0), _tokenId);
- }
- }
- /**
- * @dev Internal function to add a giphtoken ID to the list of a given address
- * @param _to address representing the new owner of the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be added to the giphtokens list of the given address
- */
- function addTokenTo(address _to, uint256 _tokenId) internal {
- require(giphyIndexToOwner[_tokenId] == address(0));
- giphyIndexToOwner[_tokenId] = _to;
- ownershipGiphyCount[_to] = ownershipGiphyCount[_to].add(1);
- }
- /**
- * @dev Internal function to remove a giphtoken ID from the list of a given address
- * @param _from address representing the previous owner of the given giphtoken ID
- * @param _tokenId uint256 ID of the giphtoken to be removed from the tokens list of the given address
- */
- function removeTokenFrom(address _from, uint256 _tokenId) internal {
- require(ownerOf(_tokenId) == _from);
- ownershipGiphyCount[_from] = ownershipGiphyCount[_from].sub(1);
- giphyIndexToOwner[_tokenId] = address(0);
- }
- /**
- * @dev Internal function to invoke `onERC721Received` on a target address
- * The call is not executed if the target address is not a contract
- * @param _from address representing the previous owner of the given giphtoken ID
- * @param _to target address that will receive the giphtokens
- * @param _tokenId uint256 ID of the giphtoken to be transferred
- * @param _data bytes optional data to send along with the call
- * @return whether the call correctly returned the expected magic value
- */
- function checkAndCallSafeTransfer(
- address _from,
- address _to,
- uint256 _tokenId,
- bytes _data
- )
- internal
- returns (bool)
- {
- if (!_to.isContract()) {
- return true;
- }
- bytes4 retval = ERC721Receiver(_to).onERC721Received(
- _from, _tokenId, _data);
- return (retval == ERC721_RECEIVED);
- }
- function createGiphtoken(string _name, string _url) public {
- uint id = giphtokens.length;
- giphtokens.push(Giphtoken(_name, _url));
- _mint(msg.sender, id);
- }
- function getMostRecentGiphtoken() public constant returns (string, string) {
- return (giphtokens[giphtokens.length].name, giphtokens[giphtokens.length].url);
- }
- }
Add Comment
Please, Sign In to add comment