As the title says, attempting to call an overloaded function from e.g. a JS test fails, since the validation for the number of function parameters fails, not taking into account that there might be 2 functions with the same name.
In a contract:
function theFn(string p1) {}
function theFn(string p1, string p2) {}
In a test:
instance.theFn.call('first param', 'second param')
will fail, since the validator in cli.bundled.js (see full stacktrace below) doesn't take into account that there could be multiple functions with the same name, but different number of parameters.
It's important to call the function that is defined last, that's the one ignored by the validator (calling the first version of the function, with only 1 param, works fine).
I would expect to be able to call an overloaded function from js tests, since it's valid Solidity.
Error: Invalid number of arguments to Solidity function
at Object.InvalidNumberOfSolidityArgs (/usr/lib/node_modules/truffle/build/cli.bundled.js:37282:16)
at SolidityFunction.validateArgs (/usr/lib/node_modules/truffle/build/cli.bundled.js:223127:22)
at SolidityFunction.toPayload (/usr/lib/node_modules/truffle/build/cli.bundled.js:223143:10)
at SolidityFunction.call (/usr/lib/node_modules/truffle/build/cli.bundled.js:223184:24)
at /usr/lib/node_modules/truffle/build/cli.bundled.js:212184:16
at Promise (<anonymous>)
at /usr/lib/node_modules/truffle/build/cli.bundled.js:212175:18
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
Ran into this issue while testing an implementation of ERC223 which overloads transfer() from ERC20.
I fixed this in our truffle fork here
https://github.com/Neufund/truffle-contract/commit/ecae09942db60039f2dc4768ceeb88776226f0ca
You call overloaded functions web3 style
const tx = await token.transfer["address,uint256,bytes"](address, initialBalance, data, { from: fromAddr });
I can provide PR to truffle-contract if maintainers are interested
I'm sure maintainers @tcoulter and @gnidan would be interested in a PR @rudolfix :)
Here it is: https://github.com/trufflesuite/truffle-contract/pull/75 @elenadimitrova
As an option, we could call overloaded methods via web3 directly, i've created an article with details https://beresnev.pro/test-overloaded-solidity-functions-via-truffle/
It's important to call the function that is defined last
No, that's not how the function "overloading" works in Solidity; it's not that the last-defined function with that name is the "real" one, but rather all functions with the same name are valid, if they have different input parameters.
From the example in the original post, if a contract has the functions:
function theFn(string p1);
function theFn(string p1, string p2);
The ABI would include something like:
[
{
name: 'theFn',
type: 'function',
inputs: [
{ "name": "p1", "type": "string" }
]
},
{
name: 'theFn',
type: 'function',
inputs: [
{ "name": "p1", "type": "string" },
{ "name": "p2", "type": "string" }
]
}
]
It would be valid to call either function, since the signature for the two is different (theFn(string) vs. theFn(string,string), which when hashed to get a ).
In this case, the Truffle testing infrastructure needs to know how to parse out:
instance.theFn.call('first param', 'second param'); // call theFn(string,string)
instance.theFn.call('first param'); // call theFn(string)
instance.theFn.call('first param', { from: accounts[3] }); // call theFn(string), using account[3]
instance.theFn.call('first param', 'second param', { from: accounts[3] }); // call theFn(string,string), using account[3]
Done this way, it would need to do some introspection on the last argument given, to see if it's an options object or some other type of input.
Looks like pull requests 75 and 94 do account for this need with two separate (but compatible options), so looks like they are correct, even though this original issue's requested resolution is not the way Solidity handles the situation.
instance.theFn.call('first param', 'second param'); // call theFn(string,string)
instance.theFn.call('first param'); // call theFn(string)
How would I call a function overload with the same number of parameters, but different types (string and uint)?
Closing this, as Truffle v4 basically had no support for overloaded functions. This is now resolved in Truffle v5. Please see the v5 release notes about overloaded functions. Thanks!
Most helpful comment
I fixed this in our truffle fork here
https://github.com/Neufund/truffle-contract/commit/ecae09942db60039f2dc4768ceeb88776226f0ca
You call overloaded functions web3 style
I can provide PR to
truffle-contractif maintainers are interested