I was wondering about this exact behaviour the other day but didn't have time to investigate it. The short answer is that Javascript itself doesn't allow for function overloading, so when the contract object is being built from the ABI, functions of the same name get overwritten.
...
The following 'homosignet' (?) contract contains three overloaded functions of the same name, the same JS argument type typeof "0x123" == "string"
but with different ABI argument types, string
, bytes
, address
contract homosignet {
function f(string s) constant returns (string){ return "was string";}
function f(bytes b) constant returns (string){ return "was bytes";}
function f(address a) constant returns (string){return "was address";}
}
We can see in Remix that the three are unique ABI functions having unique function signatures of:
fc68521a f(address)
d45754f8 f(bytes)
91e145ef f(string)
And that all three functions return the expected strings of "was string", "was bytes" and "was address".
However, if I hook the contract using web3.js and call the functions of the resulting JS object from the console, as in the following testcode and case:
<html> <head><script src="web3.js"></script>
<script>
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var homosignetContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"s","type":"string"}],"name":"f","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"b","type":"bytes"}],"name":"f","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}]);
k = homosignetContract.at("0x3b3d3de7a3271f0f6bea0b6b99e6f26a64dd3617");
</script></head></html>
> k.f(123)
"was string"
> k.f(0x123)
"was string"
> k.f("0x123")
"was string"
> k.f("test")
"was string"
The return values are all the same and in this case, all arguments are being parsed as type string
, even the number literal.
This makes sense because Javascript does not allow function overloading and when you look at the contract object, indeed only one k.f()
exists.
So it seems that calling overloaded functions requires a low level call with pre-encoded call object :
web3.eth.call(callObject [, defaultBlock] [, callback])
Which looks something like this when calling f(bytes b)
. Then you need to decode the raw return data.
web3.eth.call({to:"0x7db0be9069df82feac77f810b26a6d8011b89a8c", data:"d45754f80000000000000000000000000000000000000000000000000000000000000123"})