Truffle

錯誤:返回錯誤:處理事務時出現 VM 異常:還原(moralis 教程)

  • November 22, 2021

你們好嗎?我正在看這個影片教程,https://www.youtube.com/watch?v=y519kGkAQd8&list=RDCMUCgWS9Q3P5AxCWyQLT2kQhBw&t=235s 當我執行這個命令時

truffle migrate --network development

我收到了這個錯誤:

Error: Returned error: VM Exception while processing transaction: revert

這裡有人可以幫助我嗎?程式碼

令牌.sol

pragma solidity 0.8.10;

import "../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract Token is ERC721, Ownable {
   struct Pet {
       uint8 damage; //0-255
       uint8 magic;
       uint256 lastMeal;
       uint256 endurance; // 24 hours
   }
   uint256 nextId = 0;
   mapping(uint256 => Pet) private _tokenDetails;

   constructor(string memory name, string memory symbol)
       ERC721(name, symbol)
   {}

   function getTokenDetails(uint256 tokenId) public view returns (Pet memory) {
       return _tokenDetails[tokenId];
   }

   function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
       _safeMint(msg.sender, nextId);
       _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
       nextId++;
   }

   function feed(uint256 tokenId) public {
       Pet storage pet = _tokenDetails[nextId];
       require(pet.lastMeal + pet.endurance > block.timestamp);
       pet.lastMeal = block.timestamp;
   }

   function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override {
       Pet storage pet = _tokenDetails[nextId];
       require(pet.lastMeal + pet.endurance > block.timestamp); //Pet still alive
   }
}

2_token_migration.js

const Token = artifacts.require("Token");

module.exports = async function (deployer) {
 await deployer.deploy(Token, "NFT Game", "NFTG");
 let tokenInstance = await Token.deployed();
 await tokenInstance.mint(100,200,100000); // Token id 0
 let pet = await tokenInstance.getTokenDetails(0);
 console.log(pet)
};

有返回的錯誤

Error: Returned error: VM Exception while processing transaction: revert
   at module.exports (C:\Projetos\NFT\NFTGameMoralis\migrations\2_token_migration.js:6:23)
   at processTicksAndRejections (node:internal/process/task_queues:96:5)
   at Migration._deploy (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:75:1)
   at Migration._load (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:56:1)
   at Migration.run (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:217:1)
   at Object.runMigrations (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:150:1)
   at Object.runFrom (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:110:1)
   at Object.run (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:87:1)
   at runMigrations (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:258:1)
   at Object.run (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:223:1)
   at Command.run (C:\Users\Usuario\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\command.js:183:1)
Truffle v5.4.21 (core: 5.4.21)
Node v16.13.0

您的第一個問題在這裡:

function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
   _safeMint(msg.sender, nextId);
   _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
   nextId++;
}

_safeMint將在內部呼叫_beforeTokenTransfer. 您的實現_beforeTokenTransfer需要訪問給定 tokenId 的 Pet 結構,但這些僅在呼叫_safeMint您的程式碼後設置。

要解決此問題,您需要反轉呼叫順序:

function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
       _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
       _safeMint(msg.sender, nextId);
       nextId++;
   }

此外,我認為您的_beforeTokenTransfer實施有誤:

function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override {
       Pet storage pet = _tokenDetails[nextId];
       require(pet.lastMeal + pet.endurance > block.timestamp); //Pet still alive
   }

_tokenDetails[nextId]不可能是對的。它將通過您的鑄幣廠操作,但如果您允許轉移 NFT,則會導致不良行為。正確的實現應該使用tokenId接收的作為參數。所以像這樣:

function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override {
       Pet storage pet = _tokenDetails[tokenId];
       require(pet.lastMeal + pet.endurance > block.timestamp); //Pet still alive
   }

如果您在_beforeTokenTransfer. 使用它們,如您所見,它們非常方便。

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