Solidity

在哪裡可以找到完整的 ERC 721 範常式序?

  • December 6, 2020

我正在使用 ERC 721 令牌建構程序。我的程式碼在不使用 Open Zeppelin IERC721 提供的標準組件的情況下執行。現在我想讓它適應 ERC 721 標準。不幸的是,傳遞函式不起作用。我需要查看更多 ERC721 合約的範常式式碼,以了解編碼內容的邏輯。你知道我在哪裡可以找到更多的例子嗎?

否則,也許你直接發現了問題?我最終建構了我的程式碼並為 ERC 令牌實現了請求的函式,以便編譯器接受。在我的程式碼中,我只想使用 safeTransferFrom 函式,但傳輸不起作用。我會很感激任何建議。

到目前為止,這是我的程式碼:

// 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 {
}   
}

以下是一些可以幫助您找到範例的連結:

閱讀ERC-721 標準的底部。

引用了四個參考實現。

我認為第一個是開始 0xcert ERC-721 https://github.com/0xcert/ethereum-erc721的最佳位置

引用自:https://ethereum.stackexchange.com/questions/84531