[Ethereum] find full ERC 721 example programs

contract-developmenterc-721soliditytokens

I am building a program with an ERC 721 token. My code runs without using the standard components provided by Open Zeppelin IERC721. Now I want to adapt it to the ERC 721 standard. Unfortunately the transfer function does not work. I need to see more example codes for ERC721 contracts to understand the logic of what to code. Do you know where I can find more examples?

Otherwise, maybe you directly spot the problem? I built my code and implemented the requested functions for the ERC token in the end so the compiler accepts. In my code I only want to use the safeTransferFrom function, but the transfer is not working. I would be thankful for any advice.

This is my code so far:

// SPDX-License-Identifier: MIT
pragma experimental ABIEncoderV2;
pragma solidity ^0.6.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721Receiver.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/introspection/ERC165.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol";

contract Parknet is IERC721, ERC165  {

    
 
    
   //Save address of holder of token
    mapping (uint256 => address payable) addressTokenHolder;
    
   //Save address of creator of token
    mapping (uint256 => address payable) addressTokenCreator; 
    
   //Save name of the token 
    mapping (uint256 => string) tokenname;
    
   //Create token register 
    uint256[] tokens; 
    
    //Input from frontend: ID and token name (Later create ID by random number)
    function createNewParkspot(uint256 _tokenId, string memory _name) public isUnique(_tokenId){
    require(_tokenId != 0, "Token ID can not be 0");
    
    tokens.push(_tokenId) ;
        
     addressTokenCreator[_tokenId] = msg.sender;
     
     addressTokenHolder[_tokenId] = msg.sender;

     tokenname[_tokenId] = _name;
     
     //Save numbers of parkspots per address
     ownertokenCount[msg.sender] = (ownertokenCount[msg.sender] + 1);

     
    }
    //Show all parkspots
     function getAllIDs() public view returns (uint256[] memory) {
    return tokens;
    }
   
    //Count all parkspots
    function countParkspots() view public returns (uint) {
        return tokens.length;
    }
    //Get current holder of parkspot: Either creator or parker
    function getAddress(uint256 _tokenId) view public returns (address) {
        return (addressTokenHolder[_tokenId]);
    }   
   

    //Recieve data behind the ID: Name or in the future address, number, GPS location,...
    function getNamefromTOKENID(uint256 _tokenId) view public returns (string memory) {
    return (tokenname[_tokenId]);
    }
 
 
 
 
 
 //Create parkingfee register
    mapping (uint256 => uint) parkingfee;
    
// Creator can set fee per time of parking spot
    function SetParkingFee(uint256 _tokenId, uint _fee) public {
// Only creator can set the price     
     require (msg.sender == addressTokenCreator[_tokenId]);
  //Check if token exists
 require((_exists(_tokenId)), "Token does not exist");   
     
//input in fee/min but calculated as fee per second for technical processing 
    parkingfee[_tokenId] = _fee/60;
 
    }
    
    //See price of parkspot by entering ID
    function GetParkingFee(uint256 _tokenId) view public returns (uint) {
        return (parkingfee[_tokenId]*60);
    }
 
 


//Store start park time
mapping (uint256 => uint) parktime;

 //Store the balances of participants
 mapping(address => uint) public balances;

function StartParking (uint256 _tokenId) external payable {
 //First a deposit is required
 //Ensure balance of relevant height
 //Check if token exists
 require((_exists(_tokenId)), "Token does not exist");
 
    if(msg.value < 1000000000000000000){
        require(msg.value < 1000000000000000000, "Deposit of min. 1 ether required");
        revert();
    } 
 
  //Add deposit to balance of sender 
  else {  balances[msg.sender] += msg.value;
 
    //Transfer token ownership from creator to parker                                                         here safe transfer from 
//     addressTokenHolder[_tokenId] = msg.sender;
     
safeTransferFrom(addressTokenCreator[_tokenId], msg.sender, _tokenId);    
     
    //Save time of parking start
     parktime[_tokenId] = block.timestamp;
  
    }
}   
    
    
mapping (uint256 => uint) parkingduration;

mapping (uint256 => uint) bill;
  
  
   function EndParking (uint256 _tokenId) public payable{
      
      //Check if token exists
         require((_exists(_tokenId)), "Token does not exist");
      // Only parker can end his parking    
         require (msg.sender == addressTokenHolder[_tokenId]);  
      
       //Return park token to creator                                                                                  here safe transfer from
//       addressTokenHolder[_tokenId] = addressTokenCreator[_tokenId];
       
       
       safeTransferFrom(msg.sender, addressTokenCreator[_tokenId], _tokenId); 
       
       //Return remaining money from the deposit
       parkingduration[_tokenId] = block.timestamp - parktime[_tokenId];
       
       bill[_tokenId] = (parkingduration[_tokenId]*parkingfee[_tokenId]);
       
       //payment function included:

      //ensure deposit is high enough to pay the bill
    if (balances[msg.sender] >= bill[_tokenId]) {
     //Send fee to the creator of the parking spot    
     addressTokenCreator[_tokenId].transfer(bill[_tokenId]);
     //Subtract payment amount from deposit of parker
     balances[msg.sender] = (balances[msg.sender] - bill[_tokenId]);
     //Return remaining deposit to parker
     msg.sender.transfer(balances[msg.sender]);
    }
    //If there is not enough deposit left, the parking token returns from the parker to the creator 
    else { require(balances[msg.sender] >= bill[_tokenId], "Deposit not sufficient. Use deposit function to refill deposit and end parking again");
        }
      

   } 
    
  

 
 
 
 
 
//Receipt and control functions
 
 //For control only
    function ShowlastBill (uint256 _tokenId) view public returns (uint) {
        return bill[_tokenId];
    }
 
//Show parking duration               For control only 
  function ShowDuration (uint256 _tokenId) view public returns (uint) {
        return parkingduration[_tokenId];
    }
 
 
 //Show user balance          For control only
    function ShowDeposit () view public returns (uint) {
        return (balances[msg.sender]);
    } 

 //Show balance of the contract        For control only
 function Contractbalance() external view returns (uint){
     return address(this).balance;
 }
 
 
 
 
   function burn(uint256 _tokenId) external {
        // Error handling to check for certan conditions before transfer
        // if checks fail, all state changes from this call reverted
        require(msg.sender != address(0));
        require((_exists(_tokenId)), "Token does not exist");
        require (msg.sender == addressTokenCreator[_tokenId], "Only creator can delete token");
        
        delete tokens[_tokenId];
    
    //Save numbers of parkspots per address
     ownertokenCount[msg.sender] = (ownertokenCount[msg.sender] - 1);

    }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 //Emergency functions 
 
 
  //deposit an amount to pay for the parking spot
 function deposit() external payable {
   
   //Ensure balance of relevant height
    if(msg.value < 1 ether){
        require(msg.value < 1000000000000000000, "Deposit exceeding 1 ether required");
        revert();
    } 
  //Add deposit to balance of sender 
  else {  balances[msg.sender] += msg.value;
   //Show balance of sender
   
 } }
 
 //return the remaining funds of the deposit in case of error of normal code
 function returndeposit() public payable {
     msg.sender.transfer(balances[msg.sender]);
 }
 
 
 
 
 
 
//Technical background functions

  // Check if parkspotId exists
    function _exists(uint256 _tokenId) internal view returns (bool) {
        address owner = addressTokenCreator[_tokenId];
        return owner != address(0);
    }
    
    
  
    // Check if ID is unique and doesn't exist yet
    modifier isUnique(uint256 _tokenId) {
        bool result = true;
         
            if (addressTokenCreator[_tokenId] != address(0)) {
            
                result = false;
            }
        
        require(result, "Token with such an ID already exists.");
        _;
    }  
    



//ERC721 functions
/**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */

 function safeTransferFrom(address from, address payable to, uint256 _tokenId) public {
        require(isApproved(msg.sender));
        // solium-disable-next-line arg-overflow
        this.safeTransferFrom(from, to, _tokenId, "");
        addressTokenHolder[_tokenId] = to;
    }



 // Mapping from token ID to approve address
    mapping(uint256 => address) tokenApprovals;
    
  function approve(address _to, uint256 _tokenId) external override {
     
        tokenApprovals[_tokenId] = _to;
        emit Approval(msg.sender, _to, _tokenId);
    }



 function isApproved(address spender)
        internal
        view
        returns (bool)
    {
        address owner = msg.sender;
       
        return (spender == owner);
    }

// Return approved address for specific Pizza
    function getApproved(uint256 _tokenId) override external view returns (address operator)  {
        require(_exists(_tokenId));
        return tokenApprovals[_tokenId];
    }


  /*
     * Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     */
     
      // You can nest mappings, this example maps owner to operator approvals
    mapping(address => mapping(address => bool)) private operatorApprovals;
    
    function setApprovalForAll(address to, bool approved) public override {
        
        operatorApprovals[msg.sender][to] = approved;
        emit ApprovalForAll(msg.sender, to, approved);
    }

// Tells whether an operator is approved by a given owner
    function isApprovedForAll(address owner, address operator) override public view returns (bool)
    {
        return operatorApprovals[owner][operator];
    }









 // Returns owner of the Token found by id
    function ownerOf(uint256 _tokenId) override public view returns (address _owner) {
        return (addressTokenHolder[_tokenId]);
    }



   // Mapping from owner to number of owned token
    mapping(address => uint256) public ownertokenCount;
    // Returns count of tokens by address
    function balanceOf(address _owner) override public view returns (uint256 _balance) {
        return ownertokenCount[_owner];
    }

// Transfer token and ownership to other wallet
    function transferFrom(address _from, address _to, uint256 _tokenId) override public {
   
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) override external {
}   
}