diff --git a/contracts/interface.js b/contracts/interface.js index 643960631..3799c5cc0 100644 --- a/contracts/interface.js +++ b/contracts/interface.js @@ -614,7 +614,10 @@ function Interface(abi) { var outputNames = outputParams.names; } - var signature = method.name + '(' + inputParams.types.join(',') + ')'; + var signature = '(' + inputParams.types.join(',') + ')'; + signature = signature.replace(/tuple/g, ''); + signature = method.name + signature; + var sighash = utils.keccak256(utils.toUtf8Bytes(signature)).substring(0, 10); var func = function() { var result = { @@ -649,6 +652,7 @@ function Interface(abi) { // @TODO: Move the paraseParams defineFrozen(func, 'inputs', getKeys(method.inputs, 'name')); defineFrozen(func, 'outputs', getKeys(method.outputs, 'name')); + utils.defineProperty(func, 'signature', signature); utils.defineProperty(func, 'sighash', sighash); @@ -667,9 +671,11 @@ function Interface(abi) { var func = (function() { // @TODO: Move to parseParams var inputTypes = getKeys(method.inputs, 'type'); + var func = function() { // @TODO: Move to parseParams var signature = method.name + '(' + getKeys(method.inputs, 'type').join(',') + ')'; + var result = { inputs: method.inputs, name: method.name, @@ -747,15 +753,30 @@ function Interface(abi) { return result; }; + return populateDescription(new EventDescription(), result); } + // Next Major Version: All the event parameters are known and should + // not require a function to be called to get them. We expose them + // here now, and in the future will remove the callable version and + // replace it with the EventDescription object + + var info = func(); + // @TODO: Move to parseParams defineFrozen(func, 'inputs', getKeys(method.inputs, 'name')); + utils.defineProperty(func, 'name', info.name); + utils.defineProperty(func, 'parse', info.parse); + utils.defineProperty(func, 'signature', info.signature); + utils.defineProperty(func, 'topic', info.topics[0]); + return func; })(); + + if (method.name && events[method.name] == null) { utils.defineProperty(events, method.name, func); } diff --git a/contracts/package.json b/contracts/package.json index 406823b92..702979fc4 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,6 +1,6 @@ { "name": "ethers-contracts", - "version": "2.1.9", + "version": "2.1.10", "description": "Contract and Interface (ABI) library for Ethereum.", "bugs": { "url": "http://github.com/ethers-io/ethers.js/issues", diff --git a/tests/make-tests/make-contract-signatures.js b/tests/make-tests/make-contract-signatures.js new file mode 100644 index 000000000..0e393c59f --- /dev/null +++ b/tests/make-tests/make-contract-signatures.js @@ -0,0 +1,46 @@ +'use strict'; + +var utils = require('../utils'); + +var compile = (function() { + var soljson = require('../soljson-4.19.js'); + var _compile = soljson.cwrap("compileJSONCallback", "string", ["string", "number", "number"]); + + function compile(source) { + return JSON.parse(_compile(JSON.stringify({sources: { "demo.sol": source }}), 0)); + } + compile.version = JSON.parse(compile('contract Foo { }').contracts['demo.sol:Foo'].metadata).compiler.version + return compile; +})(); + +var tests = utils.loadTests('contract-interface-abi2'); + +var output = []; + +tests.forEach(function(test) { + var source = test.source; + var ret = source.match(/returns([^{]*){/); + var testSig = 'function testSig' + ret[1] + ' { }'; + source = source.substring(0, source.length - 2) + ' ' + testSig + '\n}\n'; + var code = compile(source); + if (!code.contracts['demo.sol:Test']) { + console.log(test.name, testSig, code.errors); + return; + } + var funcHashes = code.contracts['demo.sol:Test'].functionHashes; + var funcHash = null; + for (var key in funcHashes) { + if (key === 'test()') { continue; } + if (funcHash) { throw new Error('should not happen'); } + funcHash = key; + } + console.log(test.name, funcHash, funcHashes[funcHash]); + output.push({ + name: test.name, + signature: funcHash, + sigHash: '0x' + funcHashes[funcHash], + abi: code.contracts['demo.sol:Test'].interface + }); +}); + +utils.saveTests('contract-signatures', output); diff --git a/tests/test-contract-interface.js b/tests/test-contract-interface.js index 2dc6c559a..42d778608 100644 --- a/tests/test-contract-interface.js +++ b/tests/test-contract-interface.js @@ -321,3 +321,18 @@ describe('Test Contract Events', function() { }); }); + +describe('Test Interface Signatures', function() { + var Interface = require('../contracts').Interface; + + var tests = utils.loadTests('contract-signatures'); + tests.forEach(function(test) { + var contract = new Interface(test.abi); + it('derives the correct signature - ' + test.name, function() { + assert.equal(contract.functions.testSig.signature, test.signature, + 'derived the correct signature'); + assert.equal(contract.functions.testSig.sighash, test.sigHash, + 'derived the correct signature hash'); + }) + }); +}); diff --git a/tests/tests/contract-signatures.json.gz b/tests/tests/contract-signatures.json.gz new file mode 100644 index 000000000..e32f6b048 Binary files /dev/null and b/tests/tests/contract-signatures.json.gz differ