区块链变更 + 应付交易 Ethers.js

Blockchain altering + payable transactions with Ethers.js

我正在尝试在我的 dapp 上创建一个 mint 功能,用户可以在其中连接他们的 metamask 钱包,连接到适当的网络(在这种情况下,我只是在测试它所以它是 Goerli,chainID:5)然后单击一个 mint 按钮并被要求接受交易,目前我正在努力获取正确的语法并为交易对象设置正确的值,我收到错误:

TypeError: DenOfDragonsSigned.mint(...) is not a function 尽管这是因为我相信我已经正确设置了 ABI 和: MetaMask - RPC Error: execution reverted: Insufficient funds! 即使我已经正确设置了“值:”并且有足够的交易测试 eth

这是我的 ABI:

[
    {
        "inputs": [],
        "stateMutability": "nonpayable",
        "type": "constructor"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "internalType": "address",
                "name": "owner",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "address",
                "name": "approved",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "Approval",
        "type": "event"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "internalType": "address",
                "name": "owner",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "address",
                "name": "operator",
                "type": "address"
            },
            {
                "indexed": false,
                "internalType": "bool",
                "name": "approved",
                "type": "bool"
            }
        ],
        "name": "ApprovalForAll",
        "type": "event"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "approve",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            }
        ],
        "name": "approve1TokenForStaking",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "approveAllTokensForStaking",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "_merkleRoot",
                "type": "bytes32"
            }
        ],
        "name": "changeMerkleROOT",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "_address",
                "type": "address"
            }
        ],
        "name": "isApprovedForAll",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32[]",
                "name": "_merkleProof",
                "type": "bytes32[]"
            },
            {
                "internalType": "uint256",
                "name": "_mintAmount",
                "type": "uint256"
            }
        ],
        "name": "mint",
        "outputs": [],
        "stateMutability": "payable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_mintAmount",
                "type": "uint256"
            },
            {
                "internalType": "address",
                "name": "_receiver",
                "type": "address"
            }
        ],
        "name": "mintForAddress",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "internalType": "address",
                "name": "previousOwner",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "address",
                "name": "newOwner",
                "type": "address"
            }
        ],
        "name": "OwnershipTransferred",
        "type": "event"
    },
    {
        "inputs": [],
        "name": "renounceOwnership",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "from",
                "type": "address"
            },
            {
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "safeTransferFrom",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "from",
                "type": "address"
            },
            {
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            },
            {
                "internalType": "bytes",
                "name": "_data",
                "type": "bytes"
            }
        ],
        "name": "safeTransferFrom",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "operator",
                "type": "address"
            },
            {
                "internalType": "bool",
                "name": "approved",
                "type": "bool"
            }
        ],
        "name": "setApprovalForAll",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_cost",
                "type": "uint256"
            }
        ],
        "name": "setCost",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "string",
                "name": "_hiddenMetadataUri",
                "type": "string"
            }
        ],
        "name": "setHiddenMetadataUri",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_maxMintAmountPerTx",
                "type": "uint256"
            }
        ],
        "name": "setMaxMintAmountPerTx",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_max",
                "type": "uint256"
            }
        ],
        "name": "setMaxPresaleMintAmount",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bool",
                "name": "_open",
                "type": "bool"
            }
        ],
        "name": "setOpenToPublic",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bool",
                "name": "_state",
                "type": "bool"
            }
        ],
        "name": "setPaused",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bool",
                "name": "_state",
                "type": "bool"
            }
        ],
        "name": "setRevealed",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "_contractAddress",
                "type": "address"
            }
        ],
        "name": "setStakingAddress",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "string",
                "name": "_uriPrefix",
                "type": "string"
            }
        ],
        "name": "setUriPrefix",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "string",
                "name": "_uriSuffix",
                "type": "string"
            }
        ],
        "name": "setUriSuffix",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "internalType": "address",
                "name": "from",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "indexed": true,
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "Transfer",
        "type": "event"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "from",
                "type": "address"
            },
            {
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "transferFrom",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "newOwner",
                "type": "address"
            }
        ],
        "name": "transferOwnership",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "withdraw",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "owner",
                "type": "address"
            }
        ],
        "name": "balanceOf",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "cost",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "getApproved",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "hiddenMetadataUri",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "owner",
                "type": "address"
            },
            {
                "internalType": "address",
                "name": "operator",
                "type": "address"
            }
        ],
        "name": "isApprovedForAll",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "maxMintAmountPerTx",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "maxPresaleMintAmount",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "maxSupply",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "name",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "OpenToPublic",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "owner",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "tokenId",
                "type": "uint256"
            }
        ],
        "name": "ownerOf",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "paused",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "revealed",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "root",
        "outputs": [
            {
                "internalType": "bytes32",
                "name": "",
                "type": "bytes32"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "stakingContract",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes4",
                "name": "interfaceId",
                "type": "bytes4"
            }
        ],
        "name": "supportsInterface",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "symbol",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            }
        ],
        "name": "tokenURI",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "totalSupply",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "uriPrefix",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "uriSuffix",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "_owner",
                "type": "address"
            }
        ],
        "name": "walletOfOwner",
        "outputs": [
            {
                "internalType": "uint256[]",
                "name": "",
                "type": "uint256[]"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "name": "whitelistClaimed",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    }
]

我的App.js:

import React, { useState, useEffect } from 'react';
import "./styles.css";

import { ethers } from "ethers";
import DenOfDragonsABI from "contracts/DenOfDragons.json";
import { parseEther, parseUnits } from 'ethers/lib/utils';

let signer;
let provider;

let DenOfDragonsContract;
const DenOfDragonsAddress = "0x93e581BE9BDcCD0Cd96f5F4cbA6E5ADeA79c65ee"; // make sure this is correct
const DenOfDragonsAbi = DenOfDragonsABI;

export default function App() {
  const [metaMaskIntalled, setMetaMaskInstalled] = useState();
  const [activeAccount, setActiveAccount] = useState();
  const [activeChainID, setActiveChainID] = useState();
  const [connected, setConnected] = useState();
  const [errorMessage, setErrorMessage] = useState();
  const [balance, setBalance] = useState(0);
  const [totalSupply, setTotalSupply] = useState(0);
  
  //start of web3
  const ConnectToMetaMask = async () => {
    provider = new ethers.providers.Web3Provider(window.ethereum, "any")
    if (typeof provider !== "undefined") {
        setMetaMaskInstalled(true);
      
      await provider.send("eth_requestAccounts", []).then(accounts => {
        if (typeof accounts !== "undefined") {
    
          setActiveAccount(accounts[0]);
          console.log("Active account is:" , accounts[0]);
          setConnected(true);
        } else {
          setConnected(false);
          setActiveChainID("0")
        }
      }).catch(err => {
        console.log(err);
      });
      
      getSigner()

      window.ethereum.on("accountsChanged", function (accounts) {
        setActiveAccount(accounts[0]);
        if (typeof accounts[0] !== "undefined") {
          console.log("Active account changed to:" , accounts[0]);
          setConnected(true);
          getSigner();
        }
        else {
          console.log("Disconnected");
          setConnected(false);
          setActiveChainID("0");
        }
      })

      window.ethereum.on("chainChanged", function (chainID) {
        setActiveChainID(parseInt(chainID, 16));
        console.log("Active chainID changed to:", parseInt(chainID, 16));
        getTotalSupply();
      })


      DenOfDragonsContract = new ethers.Contract(
        DenOfDragonsAddress,
        DenOfDragonsAbi,
        provider
      );

    }
    else {setMetaMaskInstalled(false)
    };
  }

  const getSigner = async () => {
    signer = provider.getSigner();
    await signer.getChainId().then(chainID => {
      if (typeof chainID !== "undefined") {
        setActiveChainID(chainID);
        console.log("Active chainID is:", chainID);
      } 
    }).catch(err => {
      console.log(err);
    })
  }



  const mintNft = async (mintAmmount) => {
    if (connected & activeChainID === 5) {
      let cost = String((0.07 * mintAmmount) * (10 ** 18));
      console.log("Total cost:", cost);
      let gas = String(285000 * mintAmmount);
      console.log("Total gas:", gas);
      const DenOfDragonsSigned = new ethers.Contract(
        DenOfDragonsAddress,
        DenOfDragonsAbi,
        signer
      )
      const tx = DenOfDragonsSigned.mint([], mintAmmount) ({
        gasLimit: gas,
        to: DenOfDragonsAddress,
        from: activeAccount,
        value: cost,
        nonse: provider.getTransactionCount(activeAccount, "latest")
      });
      
      const signedTransaction = await signer.signTransaction(tx)
      .catch(err => {
        console.log(err)
        setErrorMessage(err["message"])
      });
      const transaction = await provider.sendTransaction(signedTransaction)
      .catch(err => {
        console.log(err)
        setErrorMessage(err["message"])
      });
      console.log(transaction);
    
    } else {
      ConnectToMetaMask();
    };
  }


  const getOwnBalance = async () => {
    if (connected & activeChainID === 1) {
      const result = await DenOfDragonsContract.balanceOf(activeAccount) 
      .catch(err => {
        console.log(err);
      });
      const balanceT = parseInt(result, 16)
      setBalance(balanceT);
      return(balanceT);

    } else {
      ConnectToMetaMask();
    };
  }


  const getTotalSupply = async () => {
    if (connected & activeChainID === 1) {
      const result = await DenOfDragonsContract.totalSupply() 
      .catch(err => {
        console.log(err);
      });
      const totalSupplyT = parseInt(result, 16)
      setTotalSupply(totalSupplyT);
      return(totalSupplyT)
    }
  }
  //end of web3



  const fetchBalance = () => {
    console.log("getting balance...")
      getOwnBalance().then(balance => {
        console.log("NFT Balance Is:", balance)
        setBalance(balance);
      });
  }



  return (
    <>
      <style>
        @import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
      </style>
      <div className='backdrop'>
        <div className='mainBox'>
          <div className='textBox'>
            <h1 className='supply'>
              {totalSupply} / 1,000
            </h1>
            <a className="etherScanLink" href="https://etherscan.io/token/0x1897D69cc0088D89C1e94889fBD2eFFfCEfEd778">
              0x1897D6...</a>
            <h2 className='price'>
              1 (NFT Name) costs (Price) ETH
            </h2>
            <h4 className='extraText'>
              Mint a (...) and become a (...) today!
            </h4>
          </div>
          <div className='mintButtonContainer'>
            {!connected ?
              <button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button> :
              <>
                {activeChainID === 5 ?
                  <>
                  <h4 className='errMsg'>
                    {errorMessage}
                  </h4>
                  <button className ="mintButton" onClick={() =>mintNft(1)}>Mint</button> 
                  </>:
                  <>
                    <h4 className='changeNetwork'>
                      Change Netwrok To Ethereum
                    </h4> 
                    <button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button>
                  </> }
              </>}
          </div>
        </div>
      </div>
    </>

  )

}

坦率地说,我不知道我做错了什么,因为这类事情非常缺乏教程,我已经阅读了 solidity、ethers.js、MetaMask 和 Ethereum 的文档,但我只是看不出问题出在哪里,感谢您提供的任何帮助

你重复调用了 mint 函数。 此外,以太币和合约工厂已经知道你不需要的地址:tofromnonce。 您可以将您的 mint 调用更改为:

const tx = DenOfDragonsSigned.mint([], mintAmmount,{
        value: cost
      });
const txHash = tx.wait();
console.log(txHash);

你应该设置好了 ;)