向智能合约汇款时出现元掩码问题

Issue with metamask when sending money to the smart contract

我是 solidity 和智能合约的新手,我对从 metamask 向我的智能合约汇款有点困惑。在 remix 中似乎一切正常,但是当我使用 metamask 时,我收到一条还原错误消息。我正在使用甘纳许作为我的本地区块链

我的智能合约是这样的:-

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.10;

   import "@openzeppelin/contracts/access/Ownable.sol";


    contract Bet is Ownable{

     
     uint public Money;  // set variable to display balance on contract
     bool Odd;  // variable to set true or false
     uint TotalDiceNumber = 12;  // dice numbers from 1 - 12
     uint result;  // variable to hold the dice roll
     mapping(address => uint)  allowance;  //allowance for non owners of the contract
     uint  BetValue;  //variable for original bet value
     uint  _amount; //variable to hold value of allowance 
     bool  Active; // is the game active
     
     

     
    constructor() {
    

    }

    

    function isOwner() internal view returns(bool) {
        return owner() == msg.sender;  //returns the address who deployed it
    }
    event BetMade(address player, uint Bet);  //placeholder to send data to front end
     function receiveMoney() public payable  {  // get money(bet) from metamask and put on smart
        emit BetMade(msg.sender, BetValue); // send player and value of bet
        //Money += BetValue;  //added after react
        Money += msg.value;
        BetValue = msg.value;
            if (owner() == msg.sender) {
                Active = false;  // owner doesnt active contract to protect funds
            } else {
                Active = true;  // player activates contract when bet is placed
                require(BetValue <= 20 ether, "Bets must be below 21 Ether"); //player can only 
          bet under 20 ether/ owner can put as much money as they want on
         }
      }
    event BalanceofContract(uint Balcontract);
       function getBalance()public returns(uint) { 
        uint Bal;
        Bal = address(this).balance;
        emit BalanceofContract(Bal);
        return Bal;
        
        
    }
    
    event PlayerSelectOddEven(address player, bool OddEven);
    function selectOddorEven(bool OddEven) public {
        emit PlayerSelectOddEven(msg.sender, OddEven);
        require(msg.sender != owner(), "You are the house and cannot bet");  // house cannot bet
        require(Active = true, "Game not in play. Please place a bet"); // game must be active
        Odd = OddEven;  // create field to enter true for odd or false for Even
        //default is false

    }

    
    function Random() internal view returns(uint) {
        return uint(keccak256(abi.encodePacked
        (block.difficulty, 
        block.timestamp, 
        TotalDiceNumber)));  // create a random number from blockchain.
        //in production would look at chainlink VR but looks like there is a cost so
        //went with a less secure option
    } 
    event RollDiceOutput(address player, uint DiceNumber);
    function Rolldice() public returns(uint){
        emit RollDiceOutput(msg.sender, result);
        uint Outcome;
        require(Active = true, "Game not in play. Please place a bet");  //game must be actvie
        Outcome = Random() % TotalDiceNumber;
        result = Outcome + 1;  // use + 1 to remove 0 out of random sequence
        return result;  // function to create number
        
        }
    function OutcomeDice() public view returns (uint) {
        uint Outcome1;
        Outcome1 = result;
        return Outcome1;
        // function to view number from above function
        }
        
    function numberOddorEven() public view returns (bool) {
        bool OddorEven;  // true for odd false for even
        uint _result;
        _result = result;
            if (_result == 1  ||  _result == 3  || _result == 5 || _result == 7 || _result == 9 || 
          _result == 11) {
                OddorEven = true; 
            } else {
                OddorEven = false;
            }
            return OddorEven;
        
            }
    event Winning(address Player, uint WinningsValue);
    function addAllowance() public   {
        emit Winning(msg.sender, _amount);  
        require(msg.sender != owner(), "You are the house and cannot bet");
        require(Active = true, "Game not in play. Please place a bet");
        address _who = msg.sender; // assign player to variable
        _amount = BetValue * 2; //assign allowance twice as much original bet
        allowance[_who] == _amount;  // set allowance in mapping against player
        
        }

    event Won(address Player, uint Winnings);               
    function WinMoney() public  {  
        emit Won(msg.sender, _amount);
        bool UserInputOdd = numberOddorEven();
        bool decisionOdd = Odd;
        address _who = msg.sender; // assign player to variable
        require(Active = true, "Game not in play. Please place a bet"); 
        require(_amount > 0, "Add the house's money by adding a allowance to collect winning");
            if (UserInputOdd == decisionOdd) {
                address payable to = payable(msg.sender);  //pay the player's address
                to.transfer(_amount); // transfer the winning
                _amount = 0; //zeroed the variable for multiplying the bet
                allowance[_who] = 0; // zeroed the allowance
                BetValue = 0; // zeroed the bet
                Odd = false; // resets the odd/even input
                Active = false;  //disable the game 

            } else {
                _amount = 0;  //zeroed the variable for multiplying the bet
                allowance[_who] = 0;  // zeroed the allowance
                BetValue = 0;  // zeroed the bet
                Odd = false;  // resets the odd/even input
                Active = false;  //disable the game 

                }
            
                                    
         }

        receive() external payable {
        receiveMoney();
      }
   }

在前端,我正在尝试向智能合约添加资金:-

import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { useState } from "react"  //import library for line 9
import { ethers } from "ethers" // import library for ethers
import { abi_file } from "../constants/abi"; // import abi from different file

export default function Home() {
  const [isConnected, setIsConnected] = useState(false);  //to show a button is not connected
  const [signer, setSigner] = useState();

  async function connect() {  //create function to connect metameask
      
    if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed
      try {
        await ethereum.request({ method: "eth_requestAccounts"});
        setIsConnected(true);  // set variable as true
        const connectedProvider = new ethers.providers.Web3Provider(window.ethereum);
        setSigner(connectedProvider.getSigner());
        } catch (e) {
          console.log(e);  // catch and log and errors in console(F12 in chrome)
        }
      } else {
      setIsConnected(false);
      }

}

async function Rolldice() {  //execute function

  if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed

    const contractAddress = "0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7";  // address of the contract
    const abi = abi_file;
    

    const contract = new ethers.Contract(contractAddress, abi, signer);  // calls the contract from the 3 variables
    
   
    try {
     // await contract.Rolldice();  //function will are calling on the sol contract
     const transactionResponse = await contract.Rolldice();
     const transactionReceipt = await transactionResponse.wait();
     var player = (transactionReceipt.events[0].args.player);
     var result = (transactionReceipt.events[0].args.DiceNumber.toString());
      //alert("Dice Number pressed");
      //var x = document.createElement("H3");
      //var t = document.createTextNode("Dice rolled from " + player);
     // x.appendChild(t);
     // document.body.appendChild(x);
      var z = document.createElement("H3");
      var w = document.createTextNode("Dice number is " + result);
      z.appendChild(w);
      document.body.appendChild(z);
           
      
    } catch (error) {
      console.log(error);
    }
  } else {
    document.getElementById("executeButton").innerHTML = 
    "Please install MetaMask";
  }
}

async function receiveMoney() {  //execute function

  if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed

    const contractAddress = "0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7";  // address of the contract
    const abi = abi_file;
    

    const contract = new ethers.Contract(contractAddress, abi, signer);  // calls the contract from the 3 variables
    
   
    try {
     // await contract.Rolldice();  //function will are calling on the sol contract
     const transactionResponse = await contract.receiveMoney();
     const transactionReceipt = await transactionResponse.wait();
      var Balance = (transactionReceipt.events[0].args.Bet.toString());
      //alert("Dice Number pressed");
      //var x = document.createElement("H3");
      //var t = document.createTextNode("Dice rolled from " + player);
     // x.appendChild(t);
     // document.body.appendChild(x);
      var z = document.createElement("H2");
      var w = document.createTextNode("The Balance of the contract is " + Balance);
      z.appendChild(w);
      document.body.appendChild(z);
           
      
    } catch (error) {
      console.log(error);
    }
  } else {
    document.getElementById("executeButton").innerHTML = 
    "Please install MetaMask";
  }
}



  return <div className={styles.container}>


  {isConnected ? 
  <>
  <h2>"Connected!" </h2>

  <p> Please send money to 0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7 but no higher than 20 ethers</p>
  
  <button onClick= {() => receiveMoney()}>Bet Money</button>
  <br></br>
  <br></br>
  <button onClick= {() => Rolldice()}>Roll dice</button>
  <br></br>
  <br></br>
  
  </>
  : (<button onClick={() =>connect()}>Connect</button>) }

   
    </div>;


   }

谁能指出我哪里出错了?非常感谢

首先,您能否在为变量 betvalue 赋值后发出事件 其次,您需要指定签名者是哪个帐户

    let provider = new ethers.providers.Web3Provider(window.ethereum); 
    const accounts = await provider.listAccounts(); 
    let account = null;
 if (accounts.length > 0) 
    { account = accounts[0] }
     let signer = provider.getSigner(account); 

第三你需要通过参数选项将用户发送的值传递给智能合约

const options = { value: ethers.utils.parseEther(value) } 

var transactionResponse = await contract.receiveMoney(options); 

值需要像这样的字符串 value="1" 这意味着您将发送 1 个以太