'solidity and react - can't get manager
I have this contract written in solidity and deployed to https://rinkeby.infura.io/:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract Lottery {
address public manager;
address[] public players;
constructor() {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint) {
return uint(keccak256(abi.encode(block.difficulty, block.timestamp, players)));
}
function pickWinner() public restricted {
uint index = random() % players.length;
payable(players[index]).transfer(address(this).balance);
players = new address[](0);
}
modifier restricted() {
require(msg.sender == manager);
_;
}
function getPlayers() public view returns(address[] memory) {
return players;
}
}
And react code:
import { useState, useEffect } from 'react';
import lottery from './lottery';
function App() {
const [manager, setManager] = useState('');
useEffect(() => {
(async () => {
const manager = await lottery.methods.manager().call();
console.log(manager)
setManager(manager);
})();
}, []);
return (
<div>
<h2>Lottery Contract</h2>
<p>This contract is managed by {manager}</p>
</div>
);
}
export default App;
But when it logs manager it's an empty array, and it should log the address of the manager. Lottery.js contains a connection to the deployed contract as well as abi and address where contract is deployed:
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'
}
];
export default new web3.eth.Contract(abi, address);
compile.js
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const lotteryPath = path.resolve(__dirname, 'contracts', 'Lottery.sol');
const source = fs.readFileSync(lotteryPath, 'utf8');
const input = {
language: 'Solidity',
sources: {
Lottery: {
content: source
}
},
settings: {
outputSelection: {
'*': {
'*': ['abi', 'evm.bytecode']
}
}
}
}
const contract = JSON.parse(solc.compile(JSON.stringify(input))).contracts.Lottery.Lottery;
module.exports = contract;
deploy.js
const HDWalletProvider = require('truffle-hdwallet-provider');
const Web3 = require('web3');
const { abi, evm } = require('./compile');
const provider = new HDWalletProvider(
'12 word secret',
'https://rinkeby.infura.io/v3/812.....adsf12'
);
const web3 = new Web3(provider);
const deploy = async() => {
const accounts = await web3.eth.getAccounts();
console.log('Attempting to deploy from account:', accounts[0]);
const result = await new web3.eth.Contract(abi)
.deploy({ data: evm.bytecode.object })
.send({ from: accounts[0], gas: '1000000' });
console.log(result._jsonInterface);
console.log(`Contract deployed to: ${result.options.address}`);
}
deploy();
I run node deploy.js and then get the address and abi and put it in my frontend application.
Solution 1:[1]
I run your code on remix and it works:
I think the problem is with the contract creation. Most likely your abi
is causing error. abi is the way how we interact with the contract, so somehow it is not correct abi
in your abi take a look at manager
:
inputs: [],
name: 'manager',
outputs: [
[Object]
],
I do not think that outputs should be Object
. you probably created abi before and then changed the contract code but forgot to create abi again.
this is from documentation
myContract.deploy({ // DATA SHOULD BE STARTING WITH "0x" data: '0x12345...', arguments: [123, 'My String'] })
try this:
const result = await new web3.eth.Contract(abi)
.deploy({ data:"0x" + evm.bytecode.object })
based on solc documentation,
input
should be like this:var input = { language: "Solidity", // you are passing Lottery sources: { "Lottery.sol": { content: source, }, }, settings: { outputSelection: { "*": { "*": ["*"], }, }, }, };
Solution 2:[2]
Works if your stringify abi
console.log(JSON.stringify(abi))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Nicolas Tassin |