0

I'm using Hardhat 2.12.7, here's my Factory contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "./SimpleToken.sol";

contract SimpleFactory {
  event Deployed(string data);
  event TokenCreated(address indexed tokenAddress, address indexed owner);

  function createToken(
    string memory name,
    string memory symbol,
    uint256 totalSupply,
    address owner
  ) public returns (address) {
    emit Deployed("Pre new");
    SimpleToken newToken = new SimpleToken(name, symbol, totalSupply, owner);
    emit TokenCreated(address(newToken), owner);
    return address(newToken);
  }
}

My Token contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract SimpleToken is ERC20 {
  constructor(
    string memory name,
    string memory symbol,
    uint256 totalSupply,
    address _owner
  ) ERC20(name, symbol) {
    _mint(_owner, totalSupply);
  }
}

It's compiled and deployed fine, through npx hardhat compile and npx hardhat run scripts/deploySimple.ts

Like this:

import { ethers } from 'hardhat';
import { ContractFactory } from 'ethers';
import { SimpleToken } from '../typechain-types/contracts/SimpleToken';
import { SimpleFactory } from '../typechain-types/contracts/SimpleFactory';

async function main() {
  const [deployer] = await ethers.getSigners();

  // Deploy SimpleToken contract
  const SimpleTokenFactory: ContractFactory = await ethers.getContractFactory(
    'SimpleToken'
  );
  const initialSupply = ethers.utils.parseUnits('1000000000', 18);
  const simpleToken: SimpleToken = <SimpleToken>(
    await SimpleTokenFactory.deploy(
      'MyToken',
      'MTK',
      initialSupply,
      deployer.address
    )
  );
  await simpleToken.deployed();
  console.log('SimpleToken deployed to:', simpleToken.address);

  // Deploy SimpleFactory contract
  const SimpleFactoryFactory: ContractFactory = await ethers.getContractFactory(
    'SimpleFactory'
  );
  const simpleFactory: SimpleFactory = <SimpleFactory>(
    await SimpleFactoryFactory.deploy()
  );
  await simpleFactory.deployed();
  console.log('SimpleFactory deployed to:', simpleFactory.address);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Then I'm using the output Factory address in my frontend app to issue a new SimpleToken through SimpleFactory. The ABI is copied from hardhat's artifacts/contracts/SimpleFactory.sol/SimpleFactory.json:

"abi": [
        {
            "anonymous": false,
            "inputs": [
                {
                    "indexed": true,
                    "internalType": "address",
                    "name": "tokenAddress",
                    "type": "address"
                },
                {
                    "indexed": true,
                    "internalType": "address",
                    "name": "owner",
                    "type": "address"
                }
            ],
            "name": "TokenCreated",
            "type": "event"
        },
        {
            "inputs": [
                {
                    "internalType": "string",
                    "name": "name",
                    "type": "string"
                },
                {
                    "internalType": "string",
                    "name": "symbol",
                    "type": "string"
                },
                {
                    "internalType": "uint256",
                    "name": "totalSupply",
                    "type": "uint256"
                },
                {
                    "internalType": "address",
                    "name": "owner",
                    "type": "address"
                }
            ],
            "name": "createToken",
            "outputs": [
                {
                    "internalType": "address",
                    "name": "",
                    "type": "address"
                }
            ],
            "stateMutability": "nonpayable",
            "type": "function"
        }
    ],
}

Maybe the problem is the lack of outputs in ABI for TokenCreated event?

And here's my frontend code:

import Web3 from 'web3'
import erc20ABI from '../../src/blockchain/abi/FactoryABI.json'
import { normalize } from '@truffle/abi-utils'
import { AbiItem } from 'web3-utils'

const NODE_URL = 'http://127.0.0.1:8545'
const DEPLOYER_ADDRESS = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
const FACTORY_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512'

const web3 = new Web3(new Web3.providers.HttpProvider(NODE_URL))
const abi = erc20ABI.abi
const normalizedAbi = normalize(abi)

const erc20Factory = new web3.eth.Contract(
    normalizedAbi as AbiItem[],
    FACTORY_ADDRESS
)

describe('Test erc20Factory interaction through Web3.js', () => {
    it('Creates new ERC20 token', async () => {
        const tokenName = 'MyTokenTest'
        const tokenSymbol = 'MTT'
        const kind = 'TITLE'
        const content = 'This is a good title'
        const decimals = 18

        const gas = await erc20Factory.methods
            .createToken(tokenName, tokenSymbol, 20000, DEPLOYER_ADDRESS)
            .estimateGas({ from: DEPLOYER_ADDRESS })
        console.log(`Calculated gas for operation: ${gas}`)

        const receipt = await erc20Factory.methods
            .createToken(tokenName, tokenSymbol, 20000, DEPLOYER_ADDRESS)
            .send({
                from: DEPLOYER_ADDRESS,
                gas: gas
            })

        const txReceipt = await web3.eth.getTransactionReceipt(
            receipt.transactionHash
        )

        const events = await erc20Factory.getPastEvents('TokenCreated', {
            fromBlock: 0,
            toBlock: 'latest'
        })

        console.log(receipt)
        console.log(txReceipt)
        console.log(events)
    })
})

export {}

The output is not what I expected. Events are empty array, and receipt/txReceipt return this:

console.log
    {
      transactionHash: '0x72ead38bed6c4c9aa5a66fb84cbbe10f16dcc0dc9ecf0f91253414895f3d6574',
      transactionIndex: 0,
      blockHash: '0x1f2237248e1bb3efa0475b3445a6242d956f6b0175533ecb413dd734607784fa',
      blockNumber: 11,
      from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
      to: '0xe7f1725e7734ce288f8367e1bb143e90bb3f0512',
      cumulativeGasUsed: 22568,
      gasUsed: 22568,
      contractAddress: null,
      logs: [],
      logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
      type: '0x2',
      status: true,
      effectiveGasPrice: 2730693045
    }

Even ChatGPT doesn't know what's going on here. Any help really appreciated.

1 Answer 1

0

You can try to wait for the transaction to be processed with .wait(), as right now you are not waiting for the transaction before using getPastEvents() - you are immediately trying to read the event but the transaction may not be finished yet.

In your code, try to implement .wait() like this:

const receipt = await erc20Factory.methods
  .createToken(tokenName, tokenSymbol, 20000, DEPLOYER_ADDRESS)
  .send({ from: DEPLOYER_ADDRESS });

// wait for the transaction
await receipt.wait();

const events = await erc20Factory.getPastEvents('TokenCreated', {
  fromBlock: 0,
  toBlock: 'latest'
});

console.log('events:', events);
1
  • Hi. Thanks for helping. It seems like .wait() method is not available to the receipt object, nor I could find it in web3.js 1.x and 4.x documentation. The issue is that there's not a single event fired, and there's more than 10 blocks already there, so it didn't work for my previous attempts too, hence nothing was logged there.
    – deb0rian
    Commented Mar 8, 2023 at 18:25

Your Answer

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

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