Web3.js: ValidateArgs cannot deal with overridden/overloaded methods

Created on 13 Jul 2017  Â·  7Comments  Â·  Source: ChainSafe/web3.js

Hey guys,

I constantly have Uncaught Error: Invalid number of arguments to Solidity function when calling only methods that are either overloaded or overridden.

The thing is that the operations passes and the actions get executed but there is error in the dev console.

My assumption is that it calls somehow all version of the methods and the versions that don't fit throw error but the one that passes just executes silently.

Trying to locate the code inside the web3.js codebase where specifying which contract method to be executed is defined.

If you have any thought just ping me.

web3 ver. 0.19.0

0.x.x

Most helpful comment

What about Events?

Transfer(address,address,uint256)
Transfer(address,address,uint256,bytes)

how do i subscribe to a specific one

All 7 comments

I've tried to simplify the bug and reproduce it into a simple contract. Though I've managed to yield different issue.

Here is the code of the contract.

pragma solidity ^0.4.12;

contract Test {

    event Logging(string msg);
    event Logging(string msg, string clarification);

    function test(string msg) {
        Logging(msg);
    }

    function test(string msg , string clarification){
        Logging(msg);
        Logging(clarification);
    }
}

I've compiled the contract and deployed it on kovan for testing purposes.
Here is the address: Etherscan

In order to test, I would like to make calls to both test methods.

const abi = [{"constant":false,"inputs":[{"name":"msg","type":"string"},{"name":"clarification","type":"string"}],"name":"test","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"msg","type":"string"}],"name":"test","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"msg","type":"string"}],"name":"Logging","type":"event"}];

const instance = web3.eth.contract(abi).at('0xdeD63e7eC47e080609fa4aF5c836A3Ff75BEe13f');

instance.test('Invoked','with two parameters',console.log); // everything goes with success



instance.test('Oh crap!',console.log) // results in error

inpage.js:8246 Uncaught Error: Invalid number of arguments to Solidity function
    at Object.InvalidNumberOfSolidityArgs (inpage.js:8245)
    at c.validateArgs (inpage.js:8246)
    at c.toPayload (inpage.js:8246)
    at c.sendTransaction (inpage.js:8246)
    at c.execute (inpage.js:8246)
    at <anonymous>:1:10

In order to access the call of test with single parameters I have to specify the signature explicitly

 instance.test['string']('Oh crap it works!',console.log);

I also hit this trying to call the overloaded ERC223 transfer function 'address,uint256,bytes' (which overloads 'address,uint256')

Referencing the function directly as you have above (in my case token.transfer['address,uint256,bytes']) fixes the validateArgs issue. However the final arg 'bytes' is not added to the data payload. So it arrives at the contract function as 0x0 ... Presumably the call is built with the 'address,uint256'.

Workaround was to build the payload manually and use web3.eth.sendTransaction to make the call.

Because of this reason there is also the function signature as well as the function name under methods. You should be able to call one of those.

myContract.methods['0x13ff5422']
// or
myContract.methods['transfer(address,uint256,bytes)']

What about Events?

Transfer(address,address,uint256)
Transfer(address,address,uint256,bytes)

how do i subscribe to a specific one

Hmmh, this is something that could be and should be fixed. At least differentiate functions by number of arguments! That could fairly simply be checked on SolidityFunction.prototype.call, then choose the proper signature to call (looking at pre-1.0 web3 now because old Truffle)

Curiously there seems to be work (arounds) being done at https://github.com/trufflesuite/truffle-contract/pull/94, which seems completely backwards. No one benefits if Truffle implements their own contract js object abstraction.

What about Events?

Transfer(address,address,uint256)
Transfer(address,address,uint256,bytes)

how do i subscribe to a specific one

@rstormsf You can do

contract.Transfer[‘address,address,uint256,address,bytes’]({
    fromBlock: 0,
    toBlock: ‘latest’
}).watch(function(error, event) {
    console.log(error, event)
})

contract.Transfer[‘address,address,uint256’]({
    fromBlock: 0,
    toBlock: ‘latest’
}).watch(function(error, event) {
    console.log(error, event)
})
Was this page helpful?
0 / 5 - 0 ratings