I’ve been trying to execute GSN tutorial. After npm run start and click the button(Increase Counter by 1) I get the following error in the browser console:
Uncaught (in promise) Error: Error: The relay hub address is set to zero in recipient at 0x5aa5142103cb6c6f01df5ccd5c3fd0cc545f78fe. Make sure it is a valid recipient contract.
The above address is Counter contract’s in the tutorial.
Environment
WSL
node 10.16.3 and npm 6.9.0
@openzeppelin/cli@2.5.3
@openzeppelin/contracts-ethereum-package@2.2.3
@openzeppelin/upgrades@2.5.3
Truffle 5.0.36
Ganache 2.1
Details
Counter contract and run-relayer(locally) deployed successfully and oz-gsn fund-recipient is OK. I confirmed the recipient balance.
Account 0x5aA5142103cb6c6f01df5CcD5C3fD0Cc545F78fe has a GSN balance of 5 ETH
Code to reproduce
Just followed the GSN tutorials.
Is it something I’ve missed? I got the local relay hub address after running the run-relayer but I don’t know how to use it(there is some configuration?)
1 Like
I found what I missed.
GSNRecipient should be initialized manually after deploying the contracts such as
foo@LAPTOP-HO37JSAG:~/sandbox/ozdapp$ oz send-tx --to 0x72BBA18033DCf231998aFC5143be15615B725D3A
Pick a network development
Select which function
❯ * initialize()
...
That calls the _upgradeRelayHub(0xD216153c06E857cD7f72665E0aF1d7D82172F494);
Looks like always same RelayHub address(in local or main/test network as doc says)
Finally tutorials works well.
P.S.
One more thing I get some red message in the browser console from Metamask when sending a transaction but app works fine.
MetaMask - RPC Error: Internal JSON-RPC error. {code: -32603, message: "Internal JSON-RPC error.", data: {…}, stack: "Error: "message" must be a nonempty string.↵ at…eogaeaoehlefnkodbefgpgknn/background.js:1:1199541"}
My app.js(I changed to SimpleStorage.sol with “old” react) is
....
async componentDidMount() {
const injectedWeb3Context = await fromInjected({gsn:{signKey: ephemeral()}});
const { accounts, networkId, networkName, providerName, lib, connected } = injectedWeb3Context;
const deployedNetwork = SimpleStorage.networks[networkId.toString()];
const contract = new lib.eth.Contract(SimpleStorage.abi, deployedNetwork.address);
this.setState({accounts, contract, networkId, lib});
lib.eth.subscribe("logs", {address: contract._address})
.on('data', (log) => {
this.handleLog(log);
})
.on('error', (err) => console.log(err));
}
handleSendTx = async () => {
const {accounts, contract} = this.state;
if (this.state.val> 0) {
this.setState({pending: !this.state.pending});
try {
await contract.methods.set(this.state.val).send({ from: accounts[0] });
} catch (err) {
console.log(err.message);
this.setState({pending: false});
}
}
}
...
I hope this post is helpful for someone like me.
1 Like
Hi @swkim109
Which tutorial were you running?
Was it the following guide: https://docs.openzeppelin.com/sdk/2.5/gsn-dapp
The guide has a note that initialize
needs to be called. How can the documentation be improved to save other people what you went through?
It is important that you remember to call the initialize()
function when creating the contract, as this will be sure to get your contract ready to be used in the GSN.
Regarding the MetaMask messages, you could try using fromConnection
rather than fromInjected
and use Infura.
1 Like
Sorry, that is what I missed. I have 2 initialize functions(one is for GSN and the other is mine) and I called my initialize().
1 Like
Hi @swkim109,
Let me know if the documentation on GSN can be improved.
Hopefully now you can update your initialize
to also call the GSNRecipient.Initialize
and also add the initializer
modifier so that your initialize
can only be called once.
See the documentation for details:
https://docs.openzeppelin.com/sdk/2.5/writing-contracts#initializers
1 Like