在 vs code 中编译 truffle 中的 OpenZeppelin 导入合约时出错

sul*_*tan 1 visual-studio ethereum solidity truffle

我正在运行一个使用truffle initCMD 命令创建的 truffle 项目。npx reate-react-app然后我在同一文件夹中创建一个反应应用程序。我正在创建一个 NFT,因此我使用npm install @openzeppelin/contracts命令在我的 React 应用程序中安装了 OZ 合约。

现在整个项目看起来像这样。

根文件夹

在此输入图像描述

包.json

在此输入图像描述

这是完整的truffle-config.js

/**
 * Use this file to configure your truffle project. It's seeded with some
 * common settings for different networks and features like migrations,
 * compilation and testing. Uncomment the ones you need or modify
 * them to suit your project as necessary.
 *
 * More information about configuration can be found at:
 *
 * trufflesuite.com/docs/advanced/configuration
 *
 * To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider)
 * to sign your transactions before they're sent to a remote public node. Infura accounts
 * are available for free at: infura.io/register.
 *
 * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate
 * public/private key pairs. If you're publishing your code to GitHub make sure you load this
 * phrase from a file you've .gitignored so it doesn't accidentally become public.
 *
 */

// const HDWalletProvider = require('@truffle/hdwallet-provider');
// const infuraKey = "fj4jll3k.....";
//
// const fs = require('fs');
// const mnemonic = fs.readFileSync(".secret").toString().trim();
const path = require("path");
module.exports = {
  contracts_build_directory: path.join(__dirname, "client/src/contracts"),
  /**
   * Networks define how you connect to your ethereum client and let you set the
   * defaults web3 uses to send transactions. If you don't specify one truffle
   * will spin up a development blockchain for you on port 9545 when you
   * run `develop` or `test`. You can ask a truffle command to use a specific
   * network from the command line, e.g
   *
   * $ truffle test --network <network-name>
   */

  networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache-cli, geth or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
     development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 7545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
     },
    // Another network with more advanced options...
    // advanced: {
    // port: 8777,             // Custom port
    // network_id: 1342,       // Custom network
    // gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
    // gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
    // from: <address>,        // Account to send txs from (default: accounts[0])
    // websocket: true        // Enable EventEmitter interface for web3 (default: false)
    // },
    // Useful for deploying to a public network.
    // NB: It's important to wrap the provider as a function.
    // ropsten: {
    // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
    // network_id: 3,       // Ropsten's id
    // gas: 5500000,        // Ropsten has a lower block limit than mainnet
    // confirmations: 2,    // # of confs to wait between deployments. (default: 0)
    // timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
    // skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },
    // Useful for private networks
    // private: {
    // provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
    // network_id: 2111,   // This network is yours, in the cloud.
    // production: true    // Treats this network as if it was a public net. (default: false)
    // }
  },

  // Set default mocha options here, use special reporters etc.
  mocha: {
    // timeout: 100000
  },

  // Configure your compilers
  compilers: {
    solc: {
       version: "0.6.1",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  },

  // Truffle DB is currently disabled by default; to enable it, change enabled: false to enabled: true
  //
  // Note: if you migrated your contracts prior to enabling this field in your Truffle project and want
  // those previously migrated contracts available in the .db directory, you will need to run the following:
  // $ truffle migrate --reset --compile-all

  db: {
    enabled: false
  }
};

Run Code Online (Sandbox Code Playgroud)

在我的 Solidity 合约文件中,路径是C:\Dapp\Pet-Shop-IPFS-React\contracts\PetShop.sol,我导入了已安装的 OZ ERC721 合约 PetShop.js

pragma solidity >=0.4.22 <0.9.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract PetShop is ERC721 {
    
      uint256 public tokenId;
      uint256 public prevOwnerTokenID;
      address public owner;
      
      mapping(uint256 => uint256) public priceMapping;
      mapping(uint256 => string) tokenIdToOffchainContentHash;
      
      event PetGenerated(address, uint256, uint256, string);
      event BuyPet(uint256, address, address);
      event SuccessfulEtherWithdrawal(uint256, address, bool);
      
       constructor()
        ERC721("ShanBuilders", "SBRS")
        {
            owner = msg.sender;
        }
     
       function generatePet(uint256 _petPrice, string memory contentHash) public returns(bool) {
         
         require(msg.sender != address(0), "Please! Check back! Registeration should not be from zero address");
         require(msg.sender == owner, "Only contract owner can generate more pets");
         
         tokenId++;
         require(tokenId <= 16, "More than 16 pets is not allowed");
         
         priceMapping[tokenId] = _petPrice;
         tokenIdToOffchainContentHash[tokenId] = contentHash;
         _mint(owner, tokenId);
         emit PetGenerated(owner, tokenId, _petPrice, contentHash);
         return true;
       }
       
       function checkPrice(uint256 _tokenId) public view returns(uint256) {
           return priceMapping[_tokenId];
       }
       
       function checkHashForAToken(uint256 _tokenId) public view returns(string memory) {
           return tokenIdToOffchainContentHash[_tokenId];
       }
       
       function buyPet(uint256 _tokenId) public payable returns(bool, string memory) {
           
           prevOwnerTokenID = _tokenId;
           address buyer = msg.sender;
           address _owner = ownerOf(prevOwnerTokenID);
           
           require(buyer != address(0), "Should not be zero address");
           require(_exists(prevOwnerTokenID), "Invalid property Id, not registered");
           require(msg.value == checkPrice(prevOwnerTokenID), "Please Send The Required Value");
           
           withDraw(msg.value);
            _transfer(_owner, buyer, prevOwnerTokenID);
           emit BuyPet(_tokenId, _owner, buyer);
           return (true, "Succesful");
       }
       
       function withDraw(uint256 _amount) internal returns(bool) {
       
        address _owner = ownerOf(prevOwnerTokenID);
        require(_amount > 0, "Amount must be valid");
        
        payable(_owner).transfer(_amount);
        emit SuccessfulEtherWithdrawal(_amount, _owner, true);
        return true;
    }
     
}
Run Code Online (Sandbox Code Playgroud)

这就是迁移

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

module.exports = function (deployer) {
  deployer.deploy(PetShop);
};

Run Code Online (Sandbox Code Playgroud)

:完成所有这些操作后,出现了一些我没有注意到的问题。当我运行truffle compile它时,编译失败并抛出错误, 在此输入图像描述

*** ParserError:找不到源“@openzeppelin/contracts/token/ERC721/ERC721.sol”:不支持文件导入回调***

我该如何解决这个问题,如果有人可以帮助我理解这个错误的含义以及为什么会发生这种情况,那就太好了?

sul*_*tan 5

我已经通过以下方式解决了它,

@openzeppelin 图书馆。我将它安装在错误的位置,在反应中,它应该安装在根文件夹中,在根文件夹中安装@openzeppelin后,它会创建package-lock.json

编译器版本为 @openzeppelin 的合约,每次都使用最新的 Solidity 版本,目前是 0.8.0,Truffle 当前版本是 5.2.0,Truffle 使用 Solidity 版本 0.5.0 或 0.5.5 之间的版本,我做了什么首先安装npm install solc@0.8.0在根文件夹中,它会package-lock.json像这样更新

"solc": {
      "version": "0.8.0",
      "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.0.tgz",
      "integrity": "sha512-ypgvqYZhb/i5BM6cw9/5QkSlDJm/rLynsbWGP3kz6HeB6oNxPK6UMiB7jMr+tNVbQbBM/8l47vrI3XaDCHShjQ==",
      "requires": {
        "command-exists": "^1.2.8",
        "commander": "3.0.2",
        "follow-redirects": "^1.12.1",
        "fs-extra": "^0.30.0",
        "js-sha3": "0.8.0",
        "memorystream": "^0.3.1",
        "require-from-string": "^2.0.0",
        "semver": "^5.5.0",
        "tmp": "0.0.33"
      }
Run Code Online (Sandbox Code Playgroud)

然后使用以下命令将 truffle 更新到0.5.3npm install -g truffle

我所做的最后一步是更新truffle-config.js以下内容:

compilers: {
    solc: {
       version: "0.8.0",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  },
Run Code Online (Sandbox Code Playgroud)

就是这样然后运行truffle compile,如果在react/src中创建了一个contract文件夹并编译成功,就不会报错

const path = require("path");
module.exports = {
  contracts_build_directory: path.join(__dirname, "client/src/contracts"),
  /**
   * Networks define how you connect to your ethereum client and let you set the
   * defaults web3 uses to send transactions. If you don't specify one truffle
   * will spin up a development blockchain for you on port 9545 when you
   * run `develop` or `test`. You can ask a truffle command to use a specific
   * network from the command line, e.g
   *
   * $ truffle test --network <network-name>
   */
Run Code Online (Sandbox Code Playgroud)