Not getting event from smart contract on ethers.js - solidity

I have contract this part is simply creating smart contract for NFT. At the end of the createToken() I am emitting event.
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.3;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address contractAddress;
event ItemCreated(
uint256 indexed tokenId
);
constructor(address marketplaceAddress) ERC721("Metaverse Tokens", "METT") {
contractAddress = marketplaceAddress;
}
function createToken(string memory tokenURI) public returns (uint) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
setApprovalForAll(contractAddress, true);
emit ItemCreated(newItemId);
}
}
I am trying to read event ItemCreated on ethers.js
const web3Model = new Web3Modal()
const connection = await web3Model.connect()
const provider = new ethers.providers.Web3Provider(connection)
const signer = provider.getSigner()
let contract = new ethers.Contract(nftaddress, NFT.abi, signer)
let transaction = await contract.createToken(url)
let tx = await transaction.wait()
console.log('tx' ,tx)
let event = tx.events[0]
console.log('event', event)
Unfortunately, the response is not giving me any event
Please see below response. evens property is empty
{
"to": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"contractAddress": null,
"transactionIndex": 0,
"gasUsed": {
"type": "BigNumber",
"hex": "0x5858"
},
"logsBloom": "0x0000000000000...",
"blockHash": "0xe66248c22832b34776c6720a6bec19bf20e9ba9af4a63ff25bd0f0689f19f037",
"transactionHash": "0xc6de2da6186ca972cc69efa265c7da5e6d780a0c25d4ad849aa4be4be9cac501",
"logs": [],
"blockNumber": 1,
"confirmations": 1,
"cumulativeGasUsed": {
"type": "BigNumber",
"hex": "0x5858"
},
"effectiveGasPrice": {
"type": "BigNumber",
"hex": "0x8d8f9fc0"
},
"status": 1,
"type": 2,
"byzantium": true,
"events": []
}
events are empty
I am sure event is emitted as I checked in hardhat-tracker
npx hardhat test --logs
NFT market
[Receiver] Transfer(from=0x0000000000000000000000000000000000000000, to=[Sender], tokenId=1)
[Receiver] ApprovalForAll(owner=[Sender], operator=0x5FbDB2315678afecb367f032d93F642f64180aa3, approved=true)
[Receiver] ItemCreated(tokenId=1)
[Receiver] Transfer(from=0x0000000000000000000000000000000000000000, to=[Sender], tokenId=2)
[Receiver] ApprovalForAll(owner=[Sender], operator=0x5FbDB2315678afecb367f032d93F642f64180aa3, approved=true)
[Receiver] ItemCreated(tokenId=2)
Any idea what I am dong wrong?
Below link to the repo https://github.com/Filip-Konkowski/Polygon-nft-market

Are you sure you have selected the correct network in your metamask? The same thing happened to me once :D Also, be sure to deploy using the network parameter such as npx hardhat run scripts/deploy.js --network localhost

Related

Could not interact with contract in BSC mainnet but succeed in testnet (but still a standard transfer)

I may send raw transaction by sendSignedTransaction to contract address on BSC testnet, and it succeed but this is just a standard transaction; it's not contract call like I want.
But on BSC mainnet, it always failed with error: Warning! Error encountered during contract execution [execution reverted]
Please help me check code below then tell me where issue, any comment, reply or guess welcome; many thanks.
For testnet, it always succeed but it was a a standard transaction, link to image. While I wanna interact with contract, result should show field Interacted With (To)
var minABI = [
{
"constant": true,
"inputs": [
{
"name": "_claimer",
"type": "uint256"
},
{
"name": "_amount",
"type": "uint256"
},
{
"name": "_sig",
"type": "bytes"
}
],
"name": "claim",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
];
var web3 = new Web3('https://data-seed-prebsc-1-s1.binance.org:8545'); // testnet
//var web3 = new Web3('https://bsc-dataseed.binance.org:443'); // mainnet
var _from = '0x2151...';
var _to = '0x7f617...';
var _sign = '0x5eddd...';
var PRIVATE_KEY = 'da65f...';
var contract = new web3.eth.Contract(minABI, _to, {from: _from});
var _nonce = await web3.eth.getTransactionCount(_from, 'latest');
var _signEncoded = contract.methods.claim(_nonce, '17390000000000000000', _sign).encodeABI();
var esGas = await web3.eth.estimateGas({
"from" : _from,
"nonce" : _nonce,
"to" : _to,
"data" : _signEncoded
});
var sentValue = gasPrice * esGas;
var transaction = {
'to': _to,
'value': sentValue,
'gas': esGas,
'nonce': _nonce,
'data': _signEncoded,
};
var signedTx = await web3.eth.accounts.signTransaction(transaction, PRIVATE_KEY);
var tx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
For mainet, if I used _signEncoded in web3.eth.estimateGas it returns error: execution reverted: Invalid signature, I must use _sign to send transaction but it still always failed with error Warning! Error encountered during contract execution [execution reverted] link to image
var esGas = await web3.eth.estimateGas({
"from" : _from,
"nonce" : _nonce,
"to" : _to,
"data" : _sign
});
Contract deployed on mainnet
But the JS snippet is trying to call the contract on testnet (where it's not deployed).
var web3 = new Web3('https://data-seed-prebsc-1-s1.binance.org:8545'); // testnet
//var web3 = new Web3('https://bsc-dataseed.binance.org:443'); // mainnet
So you need to either deploy it on testnet as well, or use a mainnet (where it's already deployed) web3 provider.
if I want to call this claim, I must call via its contract: contract.methods.claim(_nonce, 'amount', _sign).call() ? sendSignedTransaction is just a normal transfer and could not be used in my case?
The contract.methods.claim(...).call() is an shorthad for calling the function. sendSignedTransaction() can be used to send a transaction - by default without invoking any function, but you can also define its data param to execute the claim() function.
Mind that there's a difference between a call (read-only; performed by the functionName().call() in web3) and a transaction (read-write; performed by the functionName().send() function in web3). Based on the context of your question, I'm guessing you want to send a transaction (executing the claim() function) - not perform a call (to the claim() function).

Send Signed Transaction for Contract Interaction on Quorum using web3js

I am currently running the 7 nodes example given in quorum-examples github repo. I have deployed a very simple storage contract which gets and sets the value. As per the example, I am able to interact with the smart contract inside the geth node cmd line. However I would like to interact with it using another address outside the node and so I wrote the following code:
const Web3 = require('web3')
const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:22000'))
const { Transaction } = require('#ethereumjs/tx')
const { default: Common } = require('#ethereumjs/common')
const run = async () => {
const contractInstance = await new web3.eth.Contract(
[
{
constant: true,
inputs: [],
name: 'storedData',
outputs: [{ name: '', type: 'uint256' }],
payable: false,
type: 'function',
},
{
constant: false,
inputs: [{ name: 'x', type: 'uint256' }],
name: 'set',
outputs: [],
payable: false,
type: 'function',
},
{
constant: true,
inputs: [],
name: 'get',
outputs: [{ name: 'retVal', type: 'uint256' }],
payable: false,
type: 'function',
},
{
inputs: [{ name: 'initVal', type: 'uint256' }],
payable: false,
type: 'constructor',
},
],
'0xd9d64b7dc034fafdba5dc2902875a67b5d586420'
)
const customCommon = Common.forCustomChain('mainnet', {
chainId: 10,
})
const txCount = await web3.eth.getTransactionCount(
'ed9d02e382b34818e88b88a309c7fe71e65f419d'
)
const txData = {
nonce: web3.utils.toHex(txCount),
gasLimit: '0x47b760',
gasPrice: '0x00',
value: '0x0',
chainId: 10,
to: '0xd9d64b7dc034fafdba5dc2902875a67b5d586420',
data: contractInstance.methods.set(10).encodeABI(),
}
const tx = Transaction.fromTxData(txData, { common: customCommon })
const signedTx = tx.sign(
Buffer.from(
'e6181caaffff94a09d7e332fc8da9884d99902c7874eb74354bdcadf411929f1',
'hex'
)
)
const serializedTx = signedTx.serialize()
const result = await web3.eth.sendSignedTransaction(
`0x${serializedTx.toString('hex')}`
)
return result
}
run().then(console.log).catch(console.log)
However whenever I try to send the transtion, it always errors out to
"Transaction has been reverted by the EVM:\n{\n \"blockHash\": \"0xd6b06321882912185f5e1d3401a012f58b6bbf7eee1e1d2c6c2cd80a0e13bbdc\",\n \"blockNumber\": 5,\n \"contractAddress\": null,\n \"cumulativeGasUsed\": 23751,\n \"from\": \"0x0fbdc686b912d7722dc86510934589e0aaf3b55a\",\n \"gasUsed\": 23751,\n \"logs\": [],\n \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n \"status\": false,\n \"to\": \"0x9d13c6d3afe1721beef56b55d303b09e021e27ab\",\n \"transactionHash\": \"0x8c7fd175ab037e24e531804774e8b89bf5aea25de8d99aa9bc2c034229603299\",\n \"transactionIndex\": 0\n}",
Do let me know if more info is required and I will update the post.
The smartcontract code is as follows:
pragma solidity ^0.5.0;
contract simplestorage {
uint public storedData;
constructor(uint initVal) public {
storedData = initVal;
}
function set(uint x) public {
storedData = x;
}
function get() view public returns (uint retVal) {
return storedData;
}
}
I think i met the similar issue as well. My issue was invalid chain id signer. I checked many docs and tried to set the custom chain id which was what you did about "common". But nothing changed until i changed the version of ethereumjs-tx to ^1.3.7. btw you dont need common if you try my solution.

Web3.js 1.2 invocation smart contract method and can not return correct result

When I invoke the smart contract deployed, I don't get the correct result!
I have googled, but can not fine any help.
Here is my contract:
pragma solidity >=0.4.22 <0.6.0;
contract LYQFirst{
function userRegister() public payable returns(string memory)
{
return "Hello World";
}
}
and my web3.js version is 1.2 and the web3.js code is as follows:
var Web3 = require('web3');
if (typeof web3 !== 'undefined') {
console.log("Hello World");
web3 = new Web3(web3.currentProvider);
} else {
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider ("http://localhost:8545"));
}
var contract1 = new web3.eth.Contract([
{
"constant": false,
"inputs": [],
"name": "userRegister",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
],"0xd62f32665ac53749ded4a38d984d70f180d2908a");
contract1.methods.userRegister().send
({from: "0x18244fbf3b47175cd6b4a1183a476c9e70cb7368",gas:200000}).then (function(error,result){
console.log(error);
console.log("result="+result);
});
The geth including followings modules and their versions.
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0.
I installed web3.js 1.2 by npm install web3 for interacting with geth.
The result I got from web3 code is as following:
{ blockHash:
'0x4865c3845d88d7022962833b663ed298f1a0e5b2e7e4905c7b0c968972790174',
blockNumber: 3186,
contractAddress: null,
cumulativeGasUsed: 21847,
from: '0x18244fbf3b47175cd6b4a1183a476c9e70cb7368',
gasUsed: 21847,
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
root:
'0x0141214730cebc516bf7036c8b36a24af0a29dbc11ef8ef9daf05448bb84eec5',
to: '0xd62f32665ac53749ded4a38d984d70f180d2908a',
transactionHash:
'0x804d4751eb7ab6b5f31f709dafc98bfa0b7433758ac9b0d58348b34173f832b8',
transactionIndex: 0,
events: {} }
result=undefined
<<< Process finished (PID=9824). (Exit code 0)
You cannot get return value if it's a transaction (send, not call) from Javascript. Transactions return transaction receipt, and that's what you got.
If you need the value, store it an a public storage variable and call it's getter function.

Array of structs init and getter

I'm quite new to Solidity development and I'm struggling with structs for now.
I followed several examples but can't get a way to add a struct to my array of structs. My last try is:
pragma solidity ^0.4.18;
contract Iceicebaby {
struct Parcel {
string state;
string flavour;
uint256 weight;
address holder;
}
Parcel[] public parcels;
function newParcel(string _flavour, uint256 _weight) public {
parcels.length++;
parcels[parcels.length-1].state="ORDERED";
parcels[parcels.length-1].flavour=_flavour;
parcels[parcels.length-1].weight=_weight;
parcels[parcels.length-1].holder=msg.sender;
}
function getParcelsCount () view public returns (uint){
return parcels.length;
}
function getParcel(uint256 index) view public returns (string, string, uint256, address) {
return (parcels[index].state, parcels[index].flavour, parcels[index].weight ,parcels[index].holder);
}}
For now I get :
myInstance.order("Flavour",1) :
{ tx: '0xfad42f92c158557c46496df3fd104d7a09899e641e66748e57b03262f4f5fc62',
receipt:
{ transactionHash: '0xfad42f92c158557c46496df3fd104d7a09899e641e66748e57b03262f4f5fc62',
transactionIndex: 0,
blockHash: '0xc39e94e8e9e9a26fd372ad12d2eba4a72f06251d2f29c4a344cd9e58849d9e49',
blockNumber: 17,
gasUsed: 22168,
cumulativeGasUsed: 22168,
contractAddress: null,
logs: [],
status: 1 },
logs: [] }
myInstance.getParcelsCount()
BigNumber { s: 1, e: 0, c: [ 0 ] }
myInstance.getParcel(0) or myInstance.getParcel(1)
[ '', '', BigNumber { s: 1, e: 0, c: [ 0 ] }, '0x' ]
I tried several other solutions, mapping the structure and stuff like this but can't deal with this thing which should be easy, no?
Also, I can't find how to properly debbug and display logs, is there any standards for this ? I'm using truffle and a local ganache network.
Thanks !
It seems the transaction is not having enough gas to executing the code to store the data.
By default web3 sends 90000 gas (needs confirmation), which is not enough for the transaction you are trying to execute.
Change the following line of code with an extra optional parameter. Here I am providing 150000 gas to the transaction. You can have an easy estimation how much gas is required for a transaction by looking at transaction logs of remix.
myInstance.order("Flavour",1)
myInstance.order("Flavour",1, {from: web3.eth.accounts[0], gas: 150000})

Solidity (Truffle): Works fine with truffle console, but fails with truffle test

I'm running something with truffle console that works fine, but fails with truffle test.
The code is:
contract Geekt {
address[] usersByAddress;
function registerNewUser(string handle, bytes32 city, bytes32 state, bytes32 country) public returns (bool success) {
address newUserAddress = msg.sender;
usersByAddress.push(newUserAddress);
return true;
}
function getUsers() public constant returns (address[]) {
return usersByAddress;
}
}
And the tests are:
var Geekt = artifacts.require("Geekt");
contract('Geekt', function (accounts) {
it('should get initial users as empty array', function () {
return Geekt.deployed().then(function (instance) {
return instance.getUsers.call();
}).then(function (res) {
assert.equal(res.length, 0, "Expected empty array after init.");
});
});
it('should successfully add user', function () {
var geekt;
return Geekt.deployed().then(function (instance) {
geekt = instance;
return geekt.registerNewUser.call("elie222", "London", "State", "UK");
}).then(function (res) {
assert.equal(res, true, "Expected registerNewUser to return true.");
}).then(function (res) {
return geekt.getUsers.call();
}).then(function (res) {
// for debugging, but this assert passes: assert.equal(res.length, 0, "Expected array of size 0 after registerNewUser.");
// res == [] so the next line fails:
assert.equal(res.length, 1, "Expected array of size 1 after registerNewUser.");
});
});
});
It works great with truffle console:
truffle(development)> Geekt.then(function(instance){return instance.registerNewUser("Tectract","Denver","CO","USA");})
{ tx: '0x8eeea303ff9f5ceee56d71fd1265da61991749aa3d5e82db0d2d630a98fd6eb5',
receipt:
{ transactionHash: '0x8eeea303ff9f5ceee56d71fd1265da61991749aa3d5e82db0d2d630a98fd6eb5',
transactionIndex: 0,
blockHash: '0xf9a0da5ec0aba80a3338781f6d6414ceb43ec0fc023c31649a1cc347a4aba2ea',
blockNumber: 14,
gasUsed: 24566,
cumulativeGasUsed: 24566,
contractAddress: null,
logs: [] },
logs: [] }
truffle(development)> Geekt.then(function(instance){return instance.getUsers();})
[ '0x1a004a36a6bc9bcde42c6d2b237c6477cf0f535f' ]
How could this happen? What am I doing wrong?
The issue was that I was doing a call instead of a transaction.
Transactions change state whereas method calls do not and are only to read from the network.
You can read more about it here:
https://truffle.readthedocs.io/en/beta/getting_started/contracts/