web3.js icon indicating copy to clipboard operation
web3.js copied to clipboard

`web3.eth.Contract.methods.myMethod()` does not accept to insert any parameters.

Open hubts opened this issue 1 year ago • 9 comments

Expected behavior

  • Expect web3.eth.Contract.methods.myMethod(myParam) works with parameters.
  • The expectation behavior is explained in comments like below.

image

Actual behavior

  • I implemented smart contract in solidity, and already deployed it to Goerli test network.
  • ABI file was extracted, and I added the file into my code repository.
  • Thus, ABI file was OK. However, the below things are bothering me.
  • web3.eth.Contract.methods.setSystemAddress(address) does not allow the parameter (see the below image).
  • The error says You need 0 arguments, but you got 1 argument..

image

Steps to reproduce the behavior

  1. Setting as below Environment.
  2. Get ABI file into web3.eth.Contract whatever you have to generate Contract.
  3. Call web3.eth.Contract.methods.yourMethod with some parameters.
  4. The syntax does not allow you insert any parameters.

Logs

Sorry, the compile cannot be processed, any error logs cannot be provided.

Environment

  • Use yarn (classic v1) package manager
  • Use NestJS boilerplate with Node.js version 19.16.1 (also in 16.15.1)
  • Use web3 package with version 4.0.2 (maybe recent version) image
  • MacOS (M1 ChipSet)

hubts avatar Jul 12 '23 01:07 hubts

Hi there, thank you for submitting this issue. https://docs.web3js.org/guides/smart_contracts/infer_contract_types_guide/ When you define your abi make sure to define it as const like in the example above. So in your case it would be const abiFile = .... as const;. This will fix your methods and allow parameters. Let me know if you need more help :)

luu-alex avatar Jul 12 '23 15:07 luu-alex

Thank you for your quick answer. Unfortunately, I read the link, and follow some guides, however, it did not work.

As your answer, I tried: image However, the error occurs that "const" assertion can be applied to ...

Then, I tried with the link's answer like: image

This does not occur any errors on it, however, the "no parameter" problem still occurs.

image

I think with your comment, the error may occur because the type did not set from contract ABI. However, my ABI file was extracted by "Remix" and it is saved in .json file well. Here is a log to print of ABI file in the variable abiFile. (The object is wrapped with array like other ABI files.)

image image

By the way, the problem is still bothering me.

hubts avatar Jul 13 '23 04:07 hubts

Interesting case. The problem is you read the file (not import) and then convert it to const. I will investigate it.

avkos avatar Jul 18 '23 15:07 avkos

@hubts So the main problem is the Typescript can't recognize a type when you use a dynamic import. My vision to solve the problem: 1 option: convert json file to a typescript file like this one and then use it in your contract initialization.

2 option: create ABI type and assign to your imported json

type MyAbi = readonly [{
   inputs: [
                   {
                        internalType: 'address';
                        name: 'to';
                        type: 'address';
                   },
                   {
                        internalType: 'uint256';
                        name: 'amount';
                        type: 'uint256';
                   },
];
   name: 'transfer';
   outputs: [
                   {
                       internalType: 'bool';
                       name: '';
                       type: 'bool';
                   },
                  ];
   stateMutability: 'nonpayable';
   type: 'function';
}];

const abi = JSON.parse(fs.readFileSync('./ERC20Token.json', 'utf-8')).abi as unknown as MyAbi;
const contract = new Contract(abi);

contract.methods.transfer('0xe4beef667408b99053dc147ed19592ada0d77f59', 12);

avkos avatar Jul 19 '23 16:07 avkos

I encountered the same problem

rickiey avatar Jul 21 '23 01:07 rickiey

Hello @rickiey , We will look more into this. However, in the mean time as a fast fix you can try: (contract.methods.transfer as any)('0xe4beef667408b99053dc147ed19592ada0d77f59', 12); it is ugly we know. And for this will try to improve.

Muhammad-Altabba avatar Jul 25 '23 16:07 Muhammad-Altabba

Hello, @avkos Thank you for your detailed reply. First of all, the type problem you told me seems to be correct. Below are the results of my own experience with your solutions.

Option 1. Declaring a JSON file as a variable doesn't seem to work.

Like the link, it was declared as a const variable and used as a parameter for Contract. (Web3Contract is my alias for Contract)

image

image

Unfortunately, still not accepting argument.

Option 2. Creating an ABI type works for now.

I declared the const variable in Option 1 as type. I used the type to parse JSON file. Then, Contract.methods finds the type and allows argument!

image

image

Thank you for solving my problem. However, there are still questions left.

Option 1 did not work by declaring a const variable, but it is working after declaring as type in Option 2. In my thinking, the exact contract function name and arguments cannot be recognized by the type found with the variable (abi) of Contract (as Option 1). In other words, I should specify the function name and arguments using the type (as Option 2).

One thing I'm curious about is that if I do this, after I implement a contract, I will not only make the ABI json, but also copy to declare as a type. There is no exact value from type, so I should read the JSON file to get value. This means that I need to manage and match the two files, ABI json file (value) and ABI typescript file (type).

Is this the right way?

Anyway, this problem has been solved and I can continue the project!

hubts avatar Jul 31 '23 01:07 hubts

For Angular and React typescript projects the issue is still active, with a workaround as outlined above.

Additional steps still required - to extract the abi from a contract JSON artefact and manually assign as const fooAbi = [ xxx ] as const within your code.

Would be great if we could find a more seamless solution for typescript frameworks to pull directly from the full JSON contract file and avoid the extra manual work per contract. Just to recap - extracting the abi from the full JSON artefact using either import or require , encapsulating with [] as const, will result in lost method arguments.

tadpole2077 avatar Oct 20 '23 11:10 tadpole2077

Same problem, fixed it by using 'as const' at the abi. const nonceAbi = [ { inputs: [{ internalType: 'address', name: '', type: 'address' }], name: 'nonces', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function', }, ] as const;

kevinProground avatar Oct 24 '23 02:10 kevinProground