【问题标题】:I am trying to connect Lottery Contract to React Application using Metamask, But when I call manager() method on the contract I get an empty array我正在尝试使用 Metamask 将彩票合约连接到 React 应用程序,但是当我在合约上调用 manager() 方法时,我得到一个空数组
【发布时间】:2021-12-31 04:50:53
【问题描述】:

Account 数组的记录非常好,Metamask 运行正常,Ethereum 使用正常,但每次调用 manager() 时,我都会收到一个空数组,

我正在学习 Stephen Grider 的 Udemy 课程

 // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;

contract Lottery {
    address public manager;
    address payable[] public players;

    constructor(){
       manager = msg.sender;
    }

    function enter() public payable{
        require(msg.value > 0.01 ether);
        players.push(payable(msg.sender));
    }

    function random() private view returns (uint){
        return uint256(
                keccak256(
                    abi.encodePacked(block.difficulty, block.number, players)
                )
            );
    }

    function pickWinner() public restricted {
        uint index = random() % players.length;
        address contractAddress = address(this);
        players[index].transfer(contractAddress.balance);
        players = new address payable[](0);
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    function getPlayers() public view returns(address payable[] memory){
        return players;
    }
 }

前端 React Web3 启动

import Web3 from "web3";

const web3 = new Web3(window.ethereum);

export default web3;

前端 React 合约创建

import web3 from "./web3";

const contractAddress = "0x0C04a9a1587524dA1F2c65561Ca157f582242FC8";

const abi = [
  {
    inputs: [],
    stateMutability: "nonpayable",
    type: "constructor",
    constant: undefined,
    payable: undefined,
    signature: "constructor",
  },
  {
    inputs: [],
    name: "enter",
    outputs: [],
    stateMutability: "payable",
    type: "function",
    constant: undefined,
    payable: true,
    signature: "0xe97dcb62",
  },
  {
    inputs: [],
    name: "getPlayers",
    outputs: [[Object]],
    stateMutability: "view",
    type: "function",
    constant: true,
    payable: undefined,
    signature: "0x8b5b9ccc",
  },
  {
    inputs: [],
    name: "manager",
    outputs: [[Object]],
    stateMutability: "view",
    type: "function",
    constant: true,
    payable: undefined,
    signature: "0x481c6a75",
  },
  {
    inputs: [],
    name: "pickWinner",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
    constant: undefined,
    payable: undefined,
    signature: "0x5d495aea",
  },
  {
    inputs: [[Object]],
    name: "players",
    outputs: [[Object]],
    stateMutability: "view",
    type: "function",
    constant: true,
    payable: undefined,
    signature: "0xf71d96cb",
  },
];

const lottery = new web3.eth.Contract(abi, contractAddress);

export default lottery;

在 App.js 中调用合约方法:

import React, { useEffect, useRef, useState } from "react";
import web3 from "./web3";
import lottery from "./lottery";
const { ethereum } = window;

function App() {
  useEffect(() => {
    //Calling Manager
    async function getManager() {
      const account = await ethereum.request({ method: "eth_requestAccounts" });
      console.log(account);

      const manager = await lottery.methods.manager().call({
        from: account[0],
      });
      console.log(manager);
    }

    getManager();
  }, []);

  return (
    <div>
      <h2>Lottery Contract</h2>
      <p>This Contract is managed by</p>
    </div>
  );
}

export default App;

【问题讨论】:

    标签: reactjs blockchain solidity web3 web3js


    【解决方案1】:

    我运行您的代码并遇到了这个问题:

    constructor(){
           manager = msg.sender;
        }
    

    msg.sender 应付款。据我所知,你不需要明确声明它是应付的,但因为在enter 函数中你有这一行:

    players.push(payable(msg.sender));
    

    在类型严格的语言中,类型应该匹配。我运行你的solidity代码并得到这个错误:

    如果您将构造函数更改为此:

     constructor (){
            manager = payable(msg.sender);
        }
    

    现在可以了

    【讨论】:

    • 但是经理不是应付地址,只是地址
    • 当我在 remix 中运行合约时,它工作得非常好
    • 不同的编译器可能会导致问题
    【解决方案2】:

    我是刚接触 Solidity 并做出反应的新手,所以我不能 100% 确定。但似乎manager 是地址类型的变量而不是数组。既然你只是在反应中调用它,它不会是:

    const manager = await lottery.methods.manager().call();
    

    由于您只是调用/获取经理地址,我认为不需要设置/发送任何值。

    【讨论】:

    • 我也试过了,还是空数组
    • 我的第二个猜测是它在useEffect 内部。我相信这可能与async 有关。也许改用setState 会更好?
    【解决方案3】:

    从混音中复制 abi,​​而不是从控制台。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      相关资源
      最近更新 更多