当我运行部署脚本时,Hardhat 抛出“ProviderError:HttpProviderError”

问题描述 投票:0回答:2

我正在尝试将我的合约部署到 goerli 测试网,但是 Hardhat 不断抛出此错误:

Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="execution reverted", method="estimateGas", transaction={"from":"0xb5E8683Aa524069C5714Fc2D8c3e64F78f2862fb","data":"0x6103e86009556... (I shortened it down)","accessList":null}, error={"name":"ProviderError","_stack":"ProviderError: HttpProviderError\n    at HttpProvider.request (C:\\Programming\\Personal Projects\\NFT Minting Dapp\\smart-contract\\node_modules\\hardhat\\src\\internal\\core\\providers\\http.ts:78:19)\n    at LocalAccountsProvider.request (C:\\Programming\\Personal Projects\\NFT Minting Dapp\\smart-contract\\node_modules\\hardhat\\src\\internal\\core\\providers\\accounts.ts:187:34)\n    at processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async EthersProviderWrapper.send (C:\\Programming\\Personal Projects\\NFT Minting Dapp\\smart-contract\\node_modules\\@nomiclabs\\hardhat-ethers\\src\\internal\\ethers-provider-wrapper.ts:13:20)","code":3,"_isProviderError":true,"data":"0xbfc6c337000000000000000000000000fd7bfa171b5b81b79c245456e986db2f32fbfadb"}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.2)
    at Logger.makeError (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\logger\src.ts\index.ts:269:28)
    at Logger.throwError (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\logger\src.ts\index.ts:281:20)
    at checkError (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\providers\src.ts\json-rpc-provider.ts:78:20)
    at EthersProviderWrapper.<anonymous> (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\providers\src.ts\json-rpc-provider.ts:642:20)
    at step (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:48:23)
    at Object.throw (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:29:53)
    at rejected (C:\Programming\Personal Projects\NFT Minting Dapp\smart-contract\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:21:65)
    at processTicksAndRejections (node:internal/process/task_queues:95:5) {
  reason: 'execution reverted',
  code: 'UNPREDICTABLE_GAS_LIMIT',
  method: 'estimateGas',
  transaction: {
    from: '0xb5E8683Aa524069C5714Fc2D8c3e64F78f2862fb',
    data: '0x6103e86009556... (I shortened it down)',
    accessList: null
  }

这是我的合同:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @title John's ERC721A Contract
/// @author John Pioc (www.johnpioc.com)
/// @notice This contract can be used to mint ERC721A standard NFTs with industry standard functionality - whitelisted addresses, reveals, NFT metadata, etc.

import "erc721a/contracts/ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {DefaultOperatorFilterer} from "./DefaultOperatorFilterer.sol";

error CallerIsNotUser();
error InvalidWhitelistAllocation();
error MintingTooMany();
error InsufficientFunds();
error MintingOverCollectionSize();
error SaleIsClosed();
error MintingOverWhitelistAllocation();
error InvalidProof();
error URIQueryForNonexistentToken();

contract NFT is ERC721A, Ownable, DefaultOperatorFilterer {

    using Strings for uint256;

    enum SaleState {
        CLOSED,
        WHITELIST,
        PUBLIC
    }

    uint256 public collectionSize = 1000;
    uint256 public publicMintPrice = 0.1 ether;
    uint256 public publicMaxMintAmount = 3;
    uint256 public whitelistAllocation = 500;
    uint256 public whitelistMintPrice = 0.05 ether;
    uint256 public whitelistMaxMintAmount = 1;
    bytes32 public whitelistMerkleRoot;
    string public unrevealedUri = "https://exampleUnrevealedUri.com";
    string public baseUri = "https://exampleUri.com/";
    bool public isRevealed;
    SaleState public saleState;

    /// @notice Modifier to verify that caller doesn't come from a contract
    modifier callerIsUser() {
        if (tx.origin != msg.sender) revert CallerIsNotUser();
        _;
    }

    constructor() ERC721A ("NFT", "NFT") {
        isRevealed = false;
        saleState = SaleState.CLOSED;
    }

    /// @notice Function to mint NFTs during the public sale
    /// @param _mintAmount Number of NFTs to mint
    function publicMint(uint64 _mintAmount) public payable callerIsUser {
        if (_numberMinted(msg.sender) - _getAux(msg.sender) + _mintAmount > publicMaxMintAmount) revert MintingTooMany();
        if (totalSupply() + _mintAmount > collectionSize) revert MintingOverCollectionSize();
        if (saleState != SaleState.PUBLIC) revert SaleIsClosed();
        if (msg.value < _mintAmount * publicMintPrice) revert InsufficientFunds();

        _safeMint(msg.sender, _mintAmount);
    }

    /// @notice Function to mint NFTs during the whitelist sale
    /// @param _merkleProof Merkle Proof for caller's address
    /// @param _mintAmount Number of NFTs to mint
    function whitelistMint(bytes32[] calldata _merkleProof, uint64 _mintAmount) public payable callerIsUser {
        if (_getAux(msg.sender) + _mintAmount > whitelistMaxMintAmount) revert MintingTooMany();
        if (totalSupply() + _mintAmount > whitelistAllocation) revert MintingOverWhitelistAllocation();
        if (saleState != SaleState.WHITELIST) revert SaleIsClosed();
        if (msg.value < _mintAmount * whitelistMintPrice) revert InsufficientFunds();

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
        if(!(MerkleProof.verify(_merkleProof, whitelistMerkleRoot, leaf))) revert InvalidProof();

        _setAux(msg.sender, _getAux(msg.sender) + _mintAmount);
        _safeMint(msg.sender, _mintAmount);
    }

    /// @notice Sets a new collection size
    /// @dev Only owner can call this function
    /// @param _collectionSize New Collection Size
    function setCollectionSize(uint256 _collectionSize) public onlyOwner {
        collectionSize = _collectionSize;
    }

    /// @notice Sets a new public mint price
    /// @dev Only owner can call this function
    /// @param _publicMintPrice New public mint price
    function setPublicMintPrice(uint256 _publicMintPrice) public onlyOwner {
        publicMintPrice = _publicMintPrice;
    }

    /// @notice Sets a new public max mint amount
    /// @dev Only owner can call this function
    /// @param _publicMaxMintAmount New public max mint amount
    function setPublicMaxMintAmount(uint256 _publicMaxMintAmount) public onlyOwner {
        publicMaxMintAmount = _publicMaxMintAmount;
    }

    /// @notice Sets a new whitelist allocation
    /// @dev Only owner can call this function. New whitelist allocation cannot be greater than collection size
    /// @param _whitelistAllocation New whitelist allocation
    function setWhitelistAllocation(uint256 _whitelistAllocation) public onlyOwner {
        if (_whitelistAllocation > collectionSize) revert InvalidWhitelistAllocation();
        whitelistAllocation = _whitelistAllocation;
    }

    /// @notice Sets a new whitelist mint price
    /// @dev Only owner can call this function
    /// @param _whitelistMintPrice New whitelist mint price
    function setWhitelistMintPrice(uint256 _whitelistMintPrice) public onlyOwner {
        whitelistMintPrice = _whitelistMintPrice;
    }

    /// @notice Sets a new whitelist max mint amount
    /// @dev Only owner can call this function
    /// @param _whitelistMaxMintAmount New whitelist max mint amount
    function setWhitelistMaxMintAmount(uint256 _whitelistMaxMintAmount) public onlyOwner {
        whitelistMaxMintAmount = _whitelistMaxMintAmount;
    }

    /// @notice Sets a new whitelist merkle root
    /// @dev Only owner can call this function
    /// @param _whitelistMerkleRoot New whitelist merkle root
    function setWhitelistMerkleRoot(bytes32 _whitelistMerkleRoot) public onlyOwner {
        whitelistMerkleRoot = _whitelistMerkleRoot;
    }

    /// @notice Sets a new unrevealed URI
    /// @dev Only owner can call this function
    /// @param _unrevealedUri New unrevealed URI
    function setUnrevealedUri(string memory _unrevealedUri) public onlyOwner {
        unrevealedUri = _unrevealedUri;
    }

    /// @notice Sets a new base URI
    /// @dev Only owner can call this function
    /// @param _baseUri New base URI
    function setBaseUri(string memory _baseUri) public onlyOwner {
        baseUri = _baseUri;
    }

    /// @notice Toggles reveal from false to true, vice versa
    /// @dev Only owner can call this function. Starts at false
    function toggleRevealed() public onlyOwner {
        isRevealed = !isRevealed;
    }

    /// @notice Sets a new sale state
    /// @dev Only owner can call this function. 0 = CLOSED, 1 = WHITELIST, 2 = PUBLIC
    /// @param _saleState new sale state
    function setSaleState(uint256 _saleState) public onlyOwner {
        saleState = SaleState(_saleState);
    }

    /// @notice Generates and returns the token URI for a given token ID
    /// @param _tokenId An NFT's token ID
    function tokenURI(uint256 _tokenId) public view override returns (string memory) {
        if (!_exists(_tokenId)) revert URIQueryForNonexistentToken();
        if (!isRevealed) return unrevealedUri;

        return string(abi.encodePacked(baseUri, _tokenId.toString(), ".json"));
    }

    /// @notice Withdraws all ETH from contract to owner's address
    /// @dev Only owner can call this function
    function withdraw() public payable onlyOwner {
        (bool os,) = payable(owner()).call{value: address(this).balance}("");
        require(os);
    }

    /// @notice All functions below are mandatory add-ons as per the Default Operator Filterer protocol

    function transferFrom(address from, address to, uint256 tokenId) public payable override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public payable override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
        public
        payable
        override
        onlyAllowedOperator(from)
    {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

这是我的配置文件:

import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "@nomiclabs/hardhat-waffle";
import "dotenv/config";
import "@typechain/hardhat";

const GOERLI_RPC_URL = process.env.GOERLI_RPC_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.17",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
  networks: {
    goerli: {
      url: GOERLI_RPC_URL,
      accounts: [PRIVATE_KEY!],
      chainId: 5,
      allowUnlimitedContractSize: true,
    }
  },
  etherscan: {
    apiKey: {
      goerli: ETHERSCAN_API_KEY!
    }
  }
};

export default config;

这是我的部署脚本:

// imports
import { ethers, run, network } from 'hardhat';

// async main
async function main() {
  const contractFactory = await ethers.getContractFactory("NFT");
  const contract = await contractFactory.deploy();
  console.log(`Contract deployed to ${contract.address}`);

  if (network.config.chainId === 5 && process.env.ETHERSCAN_API_KEY) {
    console.log("Waiting for block confirmations...")
    await contract.deployTransaction.wait(6)
    await verify(contract.address, [])
  }
}

// async function verify(contractAddress, args) {
const verify = async (contractAddress: string, args: any[]) => {
  console.log("Verifying contract...")
  try {
    await run("verify:verify", {
      address: contractAddress,
      constructorArguments: args,
    })
  } catch (e: any) {
    if (e.message.toLowerCase().includes("already verified")) {
      console.log("Already Verified!")
    } else {
      console.log(e)
    }
  }
}

// main
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error)
    process.exit(1)
  })

我运行了命令:

npx hardhat run scripts/deploy.ts --network goerli

通过运行该命令,它会抛出错误。我仔细检查了它是否正在获取环境变量和所有内容。实际上,我从我的一个存储库中分叉了所有这些代码,当时部署脚本可以在该存储库中工作,但现在不是了

ethereum blockchain solidity hardhat
2个回答
0
投票

我在使用hardhat为goerli和主网部署时遇到了一些类似的问题。对我来说解决这个问题的方法是手动添加 Gas 限制和 Gas 价格,这是你的 goerli 配置对象应该是什么样子的,只是要注意你需要调整限制和价格以考虑当前的 Gas 价格。

goerli: {
      url: GOERLI_RPC_URL,
      accounts: [PRIVATE_KEY!],
      chainId: 5,
      allowUnlimitedContractSize: true,
      gas: 5000000, //units of gas you are willing to pay, aka gas limit
      gasPrice:  50000000000, //gas is typically in units of gwei, but you must enter it as wei here
    }

阅读安全帽配置文档也值得一看这里

检查 ETH Gas 追踪器以查看最新的 Gas 价格预估


0
投票

在安全帽配置文件中 将此属性与您的 api 密钥一起提供。

 etherscan: {
    apiKey: "",
  },

您可以通过登录etherscan(如果是主网)或basescan(如果是basenet)来获取API密钥。

© www.soinside.com 2019 - 2024. All rights reserved.