1

The manager state variable captures the value of account that deploys the contract on the network. When deploying the contract on Ganache and calling ContractName.methods.manager().call(), it returns the value of account that deploys the contract. But when I deploy the same contract using Metamask wallet on Sepolia test network, fetch the ABI and console.log the code await lottery.methods.manager().call() it in a different .js file, an empty string is returned. Unable to figure out why the function call is returning an empty array.I am using Solc compile Solidity and MOCHA to write tests.

CONTRACT

pragma solidity ^0.8.20;
contract Lottery {
    address public manager;
    address[] public players;

    constructor() {
        manager = msg.sender;
    }

    //Enter into the lottery by paying more than 0.1 Ether.
    function enter() public payable notManager {
        require(msg.value > 0.1 ether);
        players.push(msg.sender);
    }

    // Random number generator function.
    function random() private view returns (uint) {
        return
            uint(
                keccak256(
                    abi.encodePacked(block.prevrandao , block.timestamp, players)
                )
            );
    }

    //Pick winner from the player pool.
    function pickWinner() public onlyManager {
        require(manager == msg.sender);
        uint index = random() % players.length;
        address payable winner = payable(players[index]);
        uint contractBalance = address(this).balance;
        winner.transfer(contractBalance);
        players = new address[](0); // Reset the player array for a new round
    }

    //Modifier function for only manager.
    modifier onlyManager() {
        require(manager == msg.sender);
        _;
    }

    //Modifier function for not being a manager.
    modifier notManager() {
        require(manager != msg.sender);
        _;
    }

    //Returns the players array.
    function getPlayers() public view returns (address[] memory){
    return players;
    }
}

Test Code using MOCHA that return the manager value correctly.

const assert = require("assert");
const { Web3 } = require("Web3");
const ganache = require("ganache");
const { abi, evm } = require("../compile.js");

const web3 = new Web3(ganache.provider());

let lottery; //Holds instance of contract.
let accounts; //Holds all accounts provided by ganache test network.
let manager;
let players;

beforeEach(async () => {
  accounts = await web3.eth.getAccounts();

  lottery = await new web3.eth.Contract(abi)
    .deploy({ data: evm.bytecode.object })
    .send({ from: accounts[0], gas: 1000000 }); //Contract deployed by account[0].
  manager = await lottery.methods.manager().call();

  players = [];
});

describe("Lottery Contract", () => {
  it("contract deployed", async () => {
    assert.ok(lottery.options.address); //Contract deployed.
  });

  it("address is manager address", async () => {
    // console.log('manager:', manager);
    // console.log('accounts[0]', accounts[0]);
    assert.equal(manager, accounts[0]); //Contract address same as the address of the account that deployed it.
  });

});

Code that deployes to Sepolia test network.

//to deploy the code on Sepolia Etherum Network.

const config = require("./config.js");
const HDWalletProvider = require("@truffle/hdwallet-provider");
const { Web3 } = require("Web3");
const { abi, evm } = require("./compile.js");

//Creating a provider to sepolia testnet using my account.
const provider = new HDWalletProvider(
  config.seedPhrase,
  config.sepoliaTestnetUrl
);

const web3 = new Web3(provider);

const deploy = async () => {
  try {
    //Get account address from metamask
    const accounts = await web3.eth.getAccounts();

    const result = await new web3.eth.Contract(abi)
      .deploy({ data: evm.bytecode.object })
      .send({ from: accounts[0], gas: 1000000,  });

    provider.engine.stop();
  } catch (e) {
    console.log(e);
  }
};
deploy();

React Code that fetchs the contract deployed on Sepolia Network and prints on the frontend.

import logo from './logo.svg';
import './App.css';
import { Component } from 'react';
import web3 from './web3.js';
import lottery from './lottery.js';


class App extends Component{

  constructor(props){
    super(props)
    
    this.state = {manager: ''};
  }

  async componentDidMount(){
    const manager = await lottery.methods.manager().call();
    // console.log(await lottery.options.address)
    console.log(await lottery.methods.manager().call());
    this.setState({manager})
  }


render(){
  return (
    <div> 
      <h2>hi </h2>
      <h2>Lottery Contract</h2>
      <p> This contract is manager by {this.state.manager}</p>
    </div>
    
  );
}

}

export default App;

The lottery.js module that is called in App.js of the react code.

import web3 from './web3.js'
const address = '0x33Cd0B5b79df18faDFDDcc3C04316a26170153d4';//Address to which the contract is deployed to.

    const abi = [
        { inputs: [], stateMutability: 'nonpayable', type: 'constructor' },
        {
          inputs: [],
          name: 'enter',
          outputs: [],
          stateMutability: 'payable',
          type: 'function'
        },
        {
          inputs: [],
          name: 'getPlayers',
          outputs: [ [Object] ],
          stateMutability: 'view',
          type: 'function'
        },
        {
          inputs: [],
          name: 'manager',
          outputs: [ [Object] ],
          stateMutability: 'view',
          type: 'function'
        },
        {
          inputs: [],
          name: 'pickWinner',
          outputs: [],
          stateMutability: 'nonpayable',
          type: 'function'
        },
        {
          inputs: [ [Object] ],
          name: 'players',
          outputs: [ [Object] ],
          stateMutability: 'view',
          type: 'function'
        }
      ]
    
      export default new web3.eth.Contract(abi, address);

1 Answer 1

1

The issue is in the abi variable in lottery.js module. The abi should be in JSON format but this is not the case, so the contract object exported could not be read by the web3 library. Solution: send the abi parameter as a JSON using JSON.parse(abi).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.