0

The Open Zeppelin ERC20 contract has a name(), symbol, and totalSupply() function. This is my smart contract that inherits the ERC20 contract

pragma solidity ^0.8.0;

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

contract QUAD_EK is ERC20, ERC20Burnable {
    constructor(address[] memory wallets, uint256[] memory amounts) ERC20("Quadency Token", "QUAD") {
        require(wallets.length == amounts.length, "QUAD: wallets and amounts mismatch");
        for (uint256 i = 0; i < wallets.length; i++){
            _mint(wallets[i], amounts[i]);
            if(i == 10){
                break;
            }
        }
    }

I've tested that the name() function works in Truffle.

 describe('quad ek methods', async () => {
        it('gets token name', async () => {
            let quadEK = await QUAD_EK.new([account_0, account_1, account_2, account_3, account_4], amounts);
            let quadName = await quadEK.name();
            assert.equal(quadName.toString(), 'Quadency Token')
        })
    })

But when I tried to call the name() method in web3, I get the following error: TypeError: quad_ek.methods.name is not a function

My code below (the contract is loaded correctly):

 module.exports = async function(callback) {
    try{
        const web3 = new Web3(new Web3.providers.HttpProvider(
            `process.env.INFURA)`
            )
        );

        const signInfo = web3.eth.accounts.privateKeyToAccount('process.env.QUAD_TEST0')
        console.log("signingInfo", signInfo)
        const nonce = await web3.eth.getTransactionCount(signInfo.address)
        console.log("nonce", nonce)
        const quad_ek = new web3.eth.Contract(token_abi, token_address )
      **
        quad_ek.methods.name().call({from: '0x72707D86053cb767A710957a6b9D8b56Dd7Fd835'}, function(error, result){
        
         });**

    }

    catch(error){
        console.log(error)
    }

    callback()
}


I'm using the documentation from web3:

myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
    ...
});

My token abi does have the name function:

        "name()": {
          "details": "Returns the name of the token."
        },
        "symbol()": {
          "details": "Returns the symbol of the token, usually a shorter version of the name."
        },
        "totalSupply()": {
          "details": "See {IERC20-totalSupply}."
        },
        "transfer(address,uint256)": {
          "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`."
        },
        "transferFrom(address,address,uint256)": {
          "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`."
        }
Emily Kuo
  • 61
  • 4
  • Looks like the `name` function is not declared in the `token_abi` - possibly an incorrect ABI. Can you check that or share the ABI as well? – Petr Hejda Jul 10 '22 at 08:07
  • yeah the name() function is defined in the ABI; I pasted part of the ABI above – Emily Kuo Jul 10 '22 at 13:52
  • This does not seem like the correct ABI JSON format. The solution might be to pass the ABI in the expected format: https://docs.soliditylang.org/en/latest/abi-spec.html#json – Petr Hejda Jul 10 '22 at 13:59
  • Hmm, the abi was generated from truffle when I deployed to Ropsten testnet. It seems to match the solidity docs (I put a Github link to the entire ABI file) https://github.com/bubblenote/quad_EK_batch_transfers/blob/main/QUAD_EK.JSON – Emily Kuo Jul 10 '22 at 14:25

1 Answers1

1

In your post, you used the the full JSON file (or just its devDocs section, can't tell from the context) as the value of token_abi. This whole file is an output from the compilation process, it contains the ABI as well as other data produced by the compilator (bytecode, list of warnings, ...).

You need to pass just the abi section to new web3.eth.Contract();

const compileOutput = JSON.parse(fs.readFileSync("./QUAD_EK.JSON"));
const token_abi = compileOutput[0].abi;

const quad_ek = new web3.eth.Contract(token_abi, token_address);
Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • Thank you! Grabbing just the `abi` section worked. One last question (if you dont mind), I had to paste the entire abi JSON section, because this didnt work for me: `const { token_abi } = JSON.parse(fs.readFileSync('./build/contracts/QUAD_EK.json', 'utf8'))` https://stackoverflow.com/questions/72923519/file-not-found-when-reading-in-truffle-abi-file – Emily Kuo Jul 10 '22 at 17:30
  • @EmilyKuo Structure of the JSON file is an object within an array (see the `[0]` in my answer). Your JS snippet in this comment would work if the file contained just an object, not wrapped by the array. Unfortunately I don't know how to account for the array using your syntax. – Petr Hejda Jul 10 '22 at 17:35
  • Oh I was just asking why I get this `Error: ENOENT: no such file or directory, open './QUAD_EK.JSON'` error when I specifically ran: `const compileOutput = JSON.parse(fs.readFileSync("./QUAD_EK.JSON"));` or when I tried this `const { token_abi } = JSON.parse(fs.readFileSync('./build/contracts/QUAD_EK.json', 'utf8'))` – Emily Kuo Jul 10 '22 at 18:16
  • 1
    @EmilyKuo Seems like the file is located in a different directory. The `./` points to the current directory of the main JS script that you're running with nodejs. – Petr Hejda Jul 10 '22 at 18:42