Solidity
在哪裡可以找到完整的 ERC 721 範常式序?
我正在使用 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的最佳位置