solidity methods "overloading"

This commit is contained in:
Marek Kotewicz 2015-01-20 15:06:05 +01:00
parent 6a58db66f7
commit 380c1522ac
7 changed files with 111 additions and 38 deletions

66
dist/ethereum.js vendored
View File

@ -331,15 +331,37 @@ var fromAbiOutput = function (json, methodName, output) {
return result; return result;
}; };
/// @returns display name for method eg. multiply(uint256) -> multiply
var methodDisplayName = function (method) {
var length = method.indexOf('(');
return length !== -1 ? method.substr(0, length) : method;
};
/// @returns overloaded part of method's name
var methodTypeName = function (method) {
/// TODO: make it not vulnerable
var length = method.indexOf('(');
return length !== -1 ? method.substr(length + 1, method.length - 1 - (length + 1)) : "";
};
/// @param json abi for contract /// @param json abi for contract
/// @returns input parser object for given json abi /// @returns input parser object for given json abi
var inputParser = function (json) { var inputParser = function (json) {
var parser = {}; var parser = {};
json.forEach(function (method) { json.forEach(function (method) {
parser[method.name] = function () { var displayName = methodDisplayName(method.name);
var typeName = methodTypeName(method.name);
var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
return toAbiInput(json, method.name, params); return toAbiInput(json, method.name, params);
}; };
if (parser[displayName] === undefined) {
parser[displayName] = impl;
}
parser[displayName][typeName] = impl;
}); });
return parser; return parser;
@ -350,9 +372,19 @@ var inputParser = function (json) {
var outputParser = function (json) { var outputParser = function (json) {
var parser = {}; var parser = {};
json.forEach(function (method) { json.forEach(function (method) {
parser[method.name] = function (output) {
var displayName = methodDisplayName(method.name);
var typeName = methodTypeName(method.name);
var impl = function (output) {
return fromAbiOutput(json, method.name, output); return fromAbiOutput(json, method.name, output);
}; };
if (parser[displayName] === undefined) {
parser[displayName] = impl;
}
parser[displayName][typeName] = impl;
}); });
return parser; return parser;
@ -362,21 +394,15 @@ var outputParser = function (json) {
/// @param method name for which we want to get method signature /// @param method name for which we want to get method signature
/// @returns (promise) contract method signature for method with given name /// @returns (promise) contract method signature for method with given name
var methodSignature = function (json, name) { var methodSignature = function (json, name) {
var method = json[findMethodIndex(json, name)]; return web3.sha3(web3.fromAscii(name));
var result = name + '(';
var inputTypes = method.inputs.map(function (inp) {
return inp.type;
});
result += inputTypes.join(',');
result += ')';
return web3.sha3(web3.fromAscii(result));
}; };
module.exports = { module.exports = {
inputParser: inputParser, inputParser: inputParser,
outputParser: outputParser, outputParser: outputParser,
methodSignature: methodSignature methodSignature: methodSignature,
methodDisplayName: methodDisplayName,
methodTypeName: methodTypeName
}; };
@ -552,12 +578,16 @@ var contract = function (address, desc) {
var contract = {}; var contract = {};
desc.forEach(function (method) { desc.forEach(function (method) {
contract[method.name] = function () {
var displayName = abi.methodDisplayName(method.name);
var typeName = abi.methodTypeName(method.name);
var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var parsed = inputParser[method.name].apply(null, params); var parsed = inputParser[displayName][typeName].apply(null, params);
var onSuccess = function (result) { var onSuccess = function (result) {
return outputParser[method.name](result); return outputParser[displayName][typeName](result);
}; };
return { return {
@ -579,6 +609,12 @@ var contract = function (address, desc) {
} }
}; };
}; };
if (contract[displayName] === undefined) {
contract[displayName] = impl;
}
contract[displayName][typeName] = impl;
}); });
return contract; return contract;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,7 @@
// contract description, this will be autogenerated somehow // contract description, this will be autogenerated somehow
var desc = [{ var desc = [{
"name": "multiply", "name": "multiply(uint256)",
"inputs": [ "inputs": [
{ {
"name": "a", "name": "a",

View File

@ -330,15 +330,37 @@ var fromAbiOutput = function (json, methodName, output) {
return result; return result;
}; };
/// @returns display name for method eg. multiply(uint256) -> multiply
var methodDisplayName = function (method) {
var length = method.indexOf('(');
return length !== -1 ? method.substr(0, length) : method;
};
/// @returns overloaded part of method's name
var methodTypeName = function (method) {
/// TODO: make it not vulnerable
var length = method.indexOf('(');
return length !== -1 ? method.substr(length + 1, method.length - 1 - (length + 1)) : "";
};
/// @param json abi for contract /// @param json abi for contract
/// @returns input parser object for given json abi /// @returns input parser object for given json abi
var inputParser = function (json) { var inputParser = function (json) {
var parser = {}; var parser = {};
json.forEach(function (method) { json.forEach(function (method) {
parser[method.name] = function () { var displayName = methodDisplayName(method.name);
var typeName = methodTypeName(method.name);
var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
return toAbiInput(json, method.name, params); return toAbiInput(json, method.name, params);
}; };
if (parser[displayName] === undefined) {
parser[displayName] = impl;
}
parser[displayName][typeName] = impl;
}); });
return parser; return parser;
@ -349,9 +371,19 @@ var inputParser = function (json) {
var outputParser = function (json) { var outputParser = function (json) {
var parser = {}; var parser = {};
json.forEach(function (method) { json.forEach(function (method) {
parser[method.name] = function (output) {
var displayName = methodDisplayName(method.name);
var typeName = methodTypeName(method.name);
var impl = function (output) {
return fromAbiOutput(json, method.name, output); return fromAbiOutput(json, method.name, output);
}; };
if (parser[displayName] === undefined) {
parser[displayName] = impl;
}
parser[displayName][typeName] = impl;
}); });
return parser; return parser;
@ -361,20 +393,14 @@ var outputParser = function (json) {
/// @param method name for which we want to get method signature /// @param method name for which we want to get method signature
/// @returns (promise) contract method signature for method with given name /// @returns (promise) contract method signature for method with given name
var methodSignature = function (json, name) { var methodSignature = function (json, name) {
var method = json[findMethodIndex(json, name)]; return web3.sha3(web3.fromAscii(name));
var result = name + '(';
var inputTypes = method.inputs.map(function (inp) {
return inp.type;
});
result += inputTypes.join(',');
result += ')';
return web3.sha3(web3.fromAscii(result));
}; };
module.exports = { module.exports = {
inputParser: inputParser, inputParser: inputParser,
outputParser: outputParser, outputParser: outputParser,
methodSignature: methodSignature methodSignature: methodSignature,
methodDisplayName: methodDisplayName,
methodTypeName: methodTypeName
}; };

View File

@ -53,12 +53,16 @@ var contract = function (address, desc) {
var contract = {}; var contract = {};
desc.forEach(function (method) { desc.forEach(function (method) {
contract[method.name] = function () {
var displayName = abi.methodDisplayName(method.name);
var typeName = abi.methodTypeName(method.name);
var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var parsed = inputParser[method.name].apply(null, params); var parsed = inputParser[displayName][typeName].apply(null, params);
var onSuccess = function (result) { var onSuccess = function (result) {
return outputParser[method.name](result); return outputParser[displayName][typeName](result);
}; };
return { return {
@ -80,6 +84,12 @@ var contract = function (address, desc) {
} }
}; };
}; };
if (contract[displayName] === undefined) {
contract[displayName] = impl;
}
contract[displayName][typeName] = impl;
}); });
return contract; return contract;

View File

@ -48,7 +48,6 @@ describe('abi', function() {
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003");
}); });
it('should parse input uint128', function() { it('should parse input uint128', function() {
@ -321,7 +320,7 @@ describe('abi', function() {
// given // given
var d = clone(description); var d = clone(description);
d[0].name = 'helloworld'; d[0].name = 'helloworld(int)';
d[0].inputs = [ d[0].inputs = [
{ type: "int" } { type: "int" }
]; ];
@ -331,6 +330,7 @@ describe('abi', function() {
// then // then
assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001");
assert.equal(parser.helloworld['int'](1), "0000000000000000000000000000000000000000000000000000000000000001");
}); });
@ -755,7 +755,7 @@ describe('abi', function() {
// given // given
var d = clone(description); var d = clone(description);
d[0].name = 'helloworld'; d[0].name = 'helloworld(int)';
d[0].outputs = [ d[0].outputs = [
{ type: "int" } { type: "int" }
]; ];
@ -765,6 +765,7 @@ describe('abi', function() {
// then // then
assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
}); });