From 3b7fff538943ae174282c5d02ca47a6d8167015d Mon Sep 17 00:00:00 2001 From: liana Date: Wed, 14 Jan 2015 13:52:03 +0100 Subject: [PATCH 01/24] - added functionality to set values to 0 when deleting structure(not for mapping) - added unit test Made some changes after Christian`s review on pull request - remove/edit comments - BoolType and ContractType return VoidType after delete - fixed constructor_arguments test - fixed set to 0 when deleting variable from stack - changed test case to test that --- SolidityEndToEndTest.cpp | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 9543497a7..a733c2c43 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -772,6 +772,67 @@ BOOST_AUTO_TEST_CASE(struct_reference) BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(deleteStruct) +{ + char const* sourceCode = R"( + contract test { + struct topStruct { + nestedStruct nstr; + emptyStruct empty; + uint topValue; + mapping (uint => uint) topMapping; + } + uint toDelete; + topStruct str; + struct nestedStruct { + uint nestedValue; + mapping (uint => bool) nestedMapping; + } + struct emptyStruct{ + } + function test(){ + toDelete = 5; + str.topValue = 1; + str.topMapping[0] = 1; + str.topMapping[1] = 2; + + str.nstr.nestedValue = 2; + str.nstr.nestedMapping[0] = true; + str.nstr.nestedMapping[1] = false; + uint v = 5; + delete v; + delete str; + delete toDelete; + } + function getToDelete() returns (uint res){ + res = toDelete; + } + function getTopValue() returns(uint topValue){ + topValue = str.topValue; + } + function getNestedValue() returns(uint nestedValue){ + nestedValue = str.nstr.nestedValue; + } + function getTopMapping(uint index) returns(uint ret) { + ret = str.topMapping[index]; + } + function getNestedMapping(uint index) returns(bool ret) { + return str.nstr.nestedMapping[index]; + } + })"; + + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0)); + // mapping values should be the same + BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 0) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 1) == encodeArgs(2)); + BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 0) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 1) == encodeArgs(false)); +} + BOOST_AUTO_TEST_CASE(constructor) { char const* sourceCode = "contract test {\n" @@ -1243,6 +1304,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) contract Helper { string3 name; bool flag; + function Helper(string3 x, bool f) { name = x; flag = f; From dda1788082f789a24f58669af8d24ea9d0f00a8d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 15 Jan 2015 17:25:50 +0100 Subject: [PATCH 02/24] Squashed 'libjsqrc/ethereumjs/' changes from ab745d3..ec74fc0 ec74fc0 gulp 46b932c negative integers support f85f77f fixed typos 6a4b4f3 fixed readme d0473d6 gulp 70bf1a5 fixed typos bacc5aa methodExists and propertyExists are now separated tests 472ad43 more comments 603c790 next part of abi.js parsers tests and fixes b0a9bbf next part of abi.js docs 6b2ec23 formatting bool tests and fixes ed1cb9e simplifid abi.js methods 17f2f12 gulp 12bdb5f providers documentation 8d1f96c few comments 422dc05 ProviderManager separated to providermanager.js file 9a8f45e Filter separated to filter.js file 8b7d4b0 beginning of comments in web3 ee167e5 test for parsing multiple methods description 4056c04 tests... 1428dce web3.contract -> web3.eth.contract f3b71a7 removed unused line 380d986 tests in progress, fixed utf characters conversion in toAscii 9e0de57 mocha test reporter f6ff1f1 mocha reporter name starts with lower case letter 7595a5d removed padding calculation from ethereum.js, padding is always 32 9a9987a Merge commit 'a1023a5dffee7c06e8b75a21f5c9b8826e820942' into develop 5582901 Various fixes to ethereum.js and client web API stuff. ded221f Merge commit 'ab745d3b0eb89d67db1ed953020c665be3d072ed' into develop git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: ec74fc05d438806ece64fe34b0f28c8f45f5167e --- abi.parsers.js | 548 ++++++++++++++++++++++++++++++++++++++++++++++-- db.methods.js | 10 +- eth.methods.js | 52 +++-- mocha.opts | 2 +- shh.methods.js | 12 +- utils.js | 8 +- web3.methods.js | 14 +- 7 files changed, 575 insertions(+), 71 deletions(-) diff --git a/abi.parsers.js b/abi.parsers.js index 06a77fb86..925324461 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -1,37 +1,547 @@ var assert = require('assert'); var abi = require('../lib/abi.js'); +var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; + +var description = [{ + "name": "test", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] +}]; describe('abi', function() { describe('inputParser', function() { - it('should parse ...', function() { + it('should parse input uint', function() { - var desc = [{ - "name": "multiply", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input uint128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input uint256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input int', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input int128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input int256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input bool', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(true), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(false), "0000000000000000000000000000000000000000000000000000000000000000"); + + }); + + it('should parse input hash', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input hash256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + + it('should parse input hash160', function() { + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash160" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + }); + + it('should parse input address', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "address" } + ]; + + // when + var parser = abi.inputParser(d) + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input string', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "string" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('world'), "776f726c64000000000000000000000000000000000000000000000000000000"); + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld'; + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); + + }); + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] }]; - var iParser = abi.inputParser(desc); - assert.equal(iParser.multiply(1), "0x000000000000000000000000000000000000000000000000000000000000000001"); + // when + var parser = abi.inputParser(d); + + //then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test2('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); }); }); - describe('outputParser', function() { - it('parse ...', function() { + it('should parse output string', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], 'hello'); + assert.equal(parser.test("0x776f726c64000000000000000000000000000000000000000000000000000000")[0], 'world'); }); + + it('should parse output uint', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output uint256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output uint128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output hash', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output hash256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output hash160', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash160' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + // TODO shouldnt' the expected hash be shorter? + }); + + it('should parse output address', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'address' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output bool', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000001")[0], true); + assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000000")[0], false); + + + }); + + it('should parse multiple output strings', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" }, + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], 'hello'); + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], 'world'); + + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld'; + d[0].outputs = [ + { type: "int" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + + }); + + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] + }]; + + // when + var parser = abi.outputParser(d); + + //then + assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test2("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], "hello"); + + }); + }); }); diff --git a/db.methods.js b/db.methods.js index b4abfc4d7..662f4e7cc 100644 --- a/db.methods.js +++ b/db.methods.js @@ -7,12 +7,10 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('db', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.db, 'put'); - u.methodExists(web3.db, 'get'); - u.methodExists(web3.db, 'putString'); - u.methodExists(web3.db, 'getString'); - }); + u.methodExists(web3.db, 'put'); + u.methodExists(web3.db, 'get'); + u.methodExists(web3.db, 'putString'); + u.methodExists(web3.db, 'getString'); }); }); diff --git a/eth.methods.js b/eth.methods.js index 7190b27d2..892db0d8b 100644 --- a/eth.methods.js +++ b/eth.methods.js @@ -7,35 +7,31 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('eth', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.eth, 'balanceAt'); - u.methodExists(web3.eth, 'stateAt'); - u.methodExists(web3.eth, 'storageAt'); - u.methodExists(web3.eth, 'countAt'); - u.methodExists(web3.eth, 'codeAt'); - u.methodExists(web3.eth, 'transact'); - u.methodExists(web3.eth, 'call'); - u.methodExists(web3.eth, 'block'); - u.methodExists(web3.eth, 'transaction'); - u.methodExists(web3.eth, 'uncle'); - u.methodExists(web3.eth, 'compilers'); - u.methodExists(web3.eth, 'lll'); - u.methodExists(web3.eth, 'solidity'); - u.methodExists(web3.eth, 'serpent'); - u.methodExists(web3.eth, 'logs'); - }); + u.methodExists(web3.eth, 'balanceAt'); + u.methodExists(web3.eth, 'stateAt'); + u.methodExists(web3.eth, 'storageAt'); + u.methodExists(web3.eth, 'countAt'); + u.methodExists(web3.eth, 'codeAt'); + u.methodExists(web3.eth, 'transact'); + u.methodExists(web3.eth, 'call'); + u.methodExists(web3.eth, 'block'); + u.methodExists(web3.eth, 'transaction'); + u.methodExists(web3.eth, 'uncle'); + u.methodExists(web3.eth, 'compilers'); + u.methodExists(web3.eth, 'lll'); + u.methodExists(web3.eth, 'solidity'); + u.methodExists(web3.eth, 'serpent'); + u.methodExists(web3.eth, 'logs'); - it('should have all properties implemented', function () { - u.propertyExists(web3.eth, 'coinbase'); - u.propertyExists(web3.eth, 'listening'); - u.propertyExists(web3.eth, 'mining'); - u.propertyExists(web3.eth, 'gasPrice'); - u.propertyExists(web3.eth, 'account'); - u.propertyExists(web3.eth, 'accounts'); - u.propertyExists(web3.eth, 'peerCount'); - u.propertyExists(web3.eth, 'defaultBlock'); - u.propertyExists(web3.eth, 'number'); - }); + u.propertyExists(web3.eth, 'coinbase'); + u.propertyExists(web3.eth, 'listening'); + u.propertyExists(web3.eth, 'mining'); + u.propertyExists(web3.eth, 'gasPrice'); + u.propertyExists(web3.eth, 'account'); + u.propertyExists(web3.eth, 'accounts'); + u.propertyExists(web3.eth, 'peerCount'); + u.propertyExists(web3.eth, 'defaultBlock'); + u.propertyExists(web3.eth, 'number'); }); }); diff --git a/mocha.opts b/mocha.opts index b2db8d5a7..c4a633d64 100644 --- a/mocha.opts +++ b/mocha.opts @@ -1,2 +1,2 @@ ---reporter Spec +--reporter spec diff --git a/shh.methods.js b/shh.methods.js index 08f573a3c..f2f56edbc 100644 --- a/shh.methods.js +++ b/shh.methods.js @@ -7,13 +7,11 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('shh', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.shh, 'post'); - u.methodExists(web3.shh, 'newIdentity'); - u.methodExists(web3.shh, 'haveIdentity'); - u.methodExists(web3.shh, 'newGroup'); - u.methodExists(web3.shh, 'addToGroup'); - }); + u.methodExists(web3.shh, 'post'); + u.methodExists(web3.shh, 'newIdentity'); + u.methodExists(web3.shh, 'haveIdentity'); + u.methodExists(web3.shh, 'newGroup'); + u.methodExists(web3.shh, 'addToGroup'); }); }); diff --git a/utils.js b/utils.js index 4c508da67..8617348e4 100644 --- a/utils.js +++ b/utils.js @@ -1,11 +1,15 @@ var assert = require('assert'); var methodExists = function (object, method) { - assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented'); + it('should have method ' + method + ' implemented', function() { + assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented'); + }); }; var propertyExists = function (object, property) { - assert.equal('object', typeof object[property], 'property ' + property + ' is not implemented'); + it('should have property ' + property + ' implemented', function() { + assert.equal('object', typeof object[property], 'property ' + property + ' is not implemented'); + }); }; module.exports = { diff --git a/web3.methods.js b/web3.methods.js index a7e020978..5c30177e5 100644 --- a/web3.methods.js +++ b/web3.methods.js @@ -6,13 +6,11 @@ var u = require('./utils.js'); web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider describe('web3', function() { - it('should have all methods implemented', function() { - u.methodExists(web3, 'sha3'); - u.methodExists(web3, 'toAscii'); - u.methodExists(web3, 'fromAscii'); - u.methodExists(web3, 'toFixed'); - u.methodExists(web3, 'fromFixed'); - u.methodExists(web3, 'offset'); - }); + u.methodExists(web3, 'sha3'); + u.methodExists(web3, 'toAscii'); + u.methodExists(web3, 'fromAscii'); + u.methodExists(web3, 'toFixed'); + u.methodExists(web3, 'fromFixed'); + u.methodExists(web3, 'offset'); }); From 46e67c986278519ca9ba3ba2c6535dcc170a847b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 16 Jan 2015 12:07:48 +0100 Subject: [PATCH 03/24] Squashed 'libjsqrc/ethereumjs/' changes from ec74fc0..2c36d5f 2c36d5f big integers on abi.js output, tests f1295b5 tests for bigintegers on input fbcc6d0 BigNumber support git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 2c36d5ff457952c557b467e580514b08126d7dd7 --- abi.parsers.js | 109 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 7 deletions(-) diff --git a/abi.parsers.js b/abi.parsers.js index 925324461..9d255e7ad 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -1,4 +1,5 @@ var assert = require('assert'); +var BigNumber = require('bignumber.js'); var abi = require('../lib/abi.js'); var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; @@ -34,6 +35,14 @@ describe('abi', function() { // then assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); @@ -52,6 +61,14 @@ describe('abi', function() { // then assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); @@ -70,6 +87,14 @@ describe('abi', function() { // then assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); @@ -91,7 +116,14 @@ describe('abi', function() { assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); - + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); it('should parse input int128', function() { @@ -112,6 +144,14 @@ describe('abi', function() { assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); @@ -133,6 +173,14 @@ describe('abi', function() { assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + assert.equal( + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); }); @@ -312,6 +360,14 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); }); it('should parse output uint256', function() { @@ -329,6 +385,14 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); }); it('should parse output uint128', function() { @@ -346,6 +410,14 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal( + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), + new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) + ); + assert.equal( + parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), + new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) + ); }); it('should parse output int', function() { @@ -363,6 +435,8 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); }); it('should parse output int256', function() { @@ -380,6 +454,8 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); }); it('should parse output int128', function() { @@ -397,6 +473,8 @@ describe('abi', function() { // then assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); + assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); }); it('should parse output hash', function() { @@ -412,7 +490,10 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); }); it('should parse output hash256', function() { @@ -428,7 +509,10 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); }); it('should parse output hash160', function() { @@ -444,7 +528,10 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" + ); // TODO shouldnt' the expected hash be shorter? }); @@ -461,7 +548,10 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x407d73d8a49eeb85d32cf465507dd71d507100c1") + assert.equal( + parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], + "0x407d73d8a49eeb85d32cf465507dd71d507100c1" + ); }); it('should parse output bool', function() { @@ -497,8 +587,13 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], 'hello'); - assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], 'world'); + assert.equal( + parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], + 'hello' + ); + assert.equal( + parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], + 'world'); }); From ac77d20ee36c4d4b13d90926c0447a8cc4459edf Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 16 Jan 2015 12:55:49 +0100 Subject: [PATCH 04/24] Corrected "delete" for local variables i.e. set them to 0 Added test case --- SolidityEndToEndTest.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index a733c2c43..ad537750e 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -799,8 +799,6 @@ BOOST_AUTO_TEST_CASE(deleteStruct) str.nstr.nestedValue = 2; str.nstr.nestedMapping[0] = true; str.nstr.nestedMapping[1] = false; - uint v = 5; - delete v; delete str; delete toDelete; } @@ -833,6 +831,37 @@ BOOST_AUTO_TEST_CASE(deleteStruct) BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 1) == encodeArgs(false)); } +BOOST_AUTO_TEST_CASE(deleteLocal) +{ + char const* sourceCode = R"( + contract test { + function delLocal() returns (uint res){ + uint v = 5; + delete v; + res = v; + } + })"; + + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); +} + +BOOST_AUTO_TEST_CASE(deleteLocals) +{ + char const* sourceCode = R"( + contract test { + function delLocal() returns (uint res){ + uint v = 5; + uint w = 6; + delete v; + res = w; + } + })"; + + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6)); +} + BOOST_AUTO_TEST_CASE(constructor) { char const* sourceCode = "contract test {\n" From dc30fb6385bc05cf269fd813a22faf88e0c38a61 Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 16 Jan 2015 13:07:16 +0100 Subject: [PATCH 05/24] removed spaces --- SolidityEndToEndTest.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index ad537750e..18fb5e29b 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -818,9 +818,7 @@ BOOST_AUTO_TEST_CASE(deleteStruct) return str.nstr.nestedMapping[index]; } })"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0)); @@ -841,7 +839,6 @@ BOOST_AUTO_TEST_CASE(deleteLocal) res = v; } })"; - compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); } @@ -857,7 +854,6 @@ BOOST_AUTO_TEST_CASE(deleteLocals) res = w; } })"; - compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6)); } From 037d9a752806847c22758b6b6b188d11577007dd Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 16 Jan 2015 16:26:57 +0100 Subject: [PATCH 06/24] - corrected delete in case we have more than one locals - added a test --- SolidityEndToEndTest.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 18fb5e29b..eb8b22a97 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -847,15 +847,17 @@ BOOST_AUTO_TEST_CASE(deleteLocals) { char const* sourceCode = R"( contract test { - function delLocal() returns (uint res){ + function delLocal() returns (uint res1, uint res2){ uint v = 5; uint w = 6; + uint x = 7; delete v; - res = w; + res1 = w; + res2 = x; } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6)); + BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7)); } BOOST_AUTO_TEST_CASE(constructor) From adfd7d621d9313c705631c9235b8176f7b14ef22 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 16 Jan 2015 16:49:50 +0100 Subject: [PATCH 07/24] Squashed 'libjsqrc/ethereumjs/' changes from 2c36d5f..e94da80 e94da80 default padding set to 32, separated to one variable a1c0bb6 fixed checking first bit for parsing int output 774e9d2 abi.js rounds down floating point input 9a264a4 updated bower.json && package.json version, added bignumber.js to bower dependencies 0172939 fixed #28 and other small node.js issues git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: e94da808cb2a9f0493b42e5e572f6aed78de5ee3 --- abi.parsers.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/abi.parsers.js b/abi.parsers.js index 9d255e7ad..ea2e00b13 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -43,6 +43,11 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); + }); @@ -69,6 +74,10 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); @@ -95,6 +104,10 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); @@ -124,6 +137,10 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); it('should parse input int128', function() { @@ -152,6 +169,10 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); @@ -181,6 +202,10 @@ describe('abi', function() { parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); + assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); + assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); From 819226c5036a22ad978a19026d4f427d6f77d98d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sat, 17 Jan 2015 15:45:11 +0100 Subject: [PATCH 08/24] Squashed 'libjsqrc/ethereumjs/' changes from e94da80..823fb29 823fb29 tests for parsing output array 1e2c1ae output parser string support b457e88 support for int array types[] 2d8383d removed unused functions git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 823fb2995b0ff6ebaf257206ad1ecf827b8567b8 --- abi.parsers.js | 135 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 27 deletions(-) diff --git a/abi.parsers.js b/abi.parsers.js index ea2e00b13..740d52eca 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -40,9 +40,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -71,9 +71,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -101,9 +101,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -134,9 +134,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -166,9 +166,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -199,9 +199,9 @@ describe('abi', function() { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); + parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -307,8 +307,14 @@ describe('abi', function() { var parser = abi.inputParser(d); // then - assert.equal(parser.test('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('world'), "776f726c64000000000000000000000000000000000000000000000000000000"); + assert.equal( + parser.test('hello'), + "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" + ); + assert.equal( + parser.test('world'), + "0000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000" + ); }); it('should use proper method name', function () { @@ -346,9 +352,34 @@ describe('abi', function() { //then assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test2('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); + assert.equal( + parser.test2('hello'), + "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" + ); }); + + it('should parse input array of ints', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int[]" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test([5, 6]), + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006" + ); + }); + }); describe('outputParser', function() { @@ -365,8 +396,18 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], 'hello'); - assert.equal(parser.test("0x776f726c64000000000000000000000000000000000000000000000000000000")[0], 'world'); + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], + 'hello' + ); + assert.equal( + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "776f726c64000000000000000000000000000000000000000000000000000000")[0], + 'world' + ); }); @@ -613,12 +654,21 @@ describe('abi', function() { // then assert.equal( - parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + + "776f726c64000000000000000000000000000000000000000000000000000000")[0], 'hello' ); assert.equal( - parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], - 'world'); + parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + + "776f726c64000000000000000000000000000000000000000000000000000000")[1], + 'world' + ); }); @@ -658,7 +708,38 @@ describe('abi', function() { //then assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test2("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], "hello"); + assert.equal(parser.test2("0x" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], + "hello" + ); + + }); + + it('should parse output array', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'int[]' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006")[0][0], + 5 + ); + assert.equal(parser.test("0x" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006")[0][1], + 6 + ); }); From 21e037c74fbc5aeba83d18a02f072b94d1a70542 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 19 Jan 2015 13:53:44 +0100 Subject: [PATCH 09/24] Squashed 'libjsqrc/ethereumjs/' changes from 823fb29..6a58db6 6a58db6 parsing real, ureal values on output af54832 encoding real on input 86b417e fixes for autoprovider git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 6a58db66f7f42a49667bcc751418256441752279 --- abi.parsers.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/abi.parsers.js b/abi.parsers.js index 740d52eca..e9613817b 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -380,6 +380,45 @@ describe('abi', function() { ); }); + it('should parse input real', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'real' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); + + }); + + it('should parse input ureal', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'ureal' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + + }); + }); describe('outputParser', function() { @@ -633,12 +672,52 @@ describe('abi', function() { var parser = abi.outputParser(d); // then - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000001")[0], true); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000000")[0], false); + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true); + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false); }); + it('should parse output real', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'real' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); + assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); + assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); + assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1); + + }); + + it('should parse output ureal', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'ureal' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); + assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); + assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); + + }); + + it('should parse multiple output strings', function() { // given From 933d65e9863e4f1d57500ccba85e6cde116d962a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 19 Jan 2015 15:34:15 +0100 Subject: [PATCH 10/24] Some addition to Solidity Execution Framework --- solidityExecutionFramework.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h index 8d3c7e77c..1160d046f 100644 --- a/solidityExecutionFramework.h +++ b/solidityExecutionFramework.h @@ -29,6 +29,7 @@ #include #include #include +#include "TestHelper.h" namespace dev { @@ -46,7 +47,20 @@ public: bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") { dev::solidity::CompilerStack compiler; - compiler.compile(_sourceCode, m_optimize); + try + { + compiler.compile(_sourceCode, m_optimize); + } + catch (const std::exception& e) + { + std::string const* extra = boost::get_error_info(e); + std::string msg = std::string("Parsing contract failed with: ") + + e.what() + std::string("\n"); + if (extra) + msg += *extra; + BOOST_FAIL(msg); + } + bytes code = compiler.getBytecode(_contractName); sendMessage(code, true, _value); BOOST_REQUIRE(!m_output.empty()); @@ -97,6 +111,7 @@ public: static bytes encode(char const* _value) { return encode(std::string(_value)); } static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; } static bytes encode(u256 const& _value) { return toBigEndian(_value); } + static bytes encode(h256 const& _value) { return _value.asBytes(); } static bytes encode(bytes const& _value, bool _padLeft = true) { bytes padding = bytes((32 - _value.size() % 32) % 32, 0); @@ -114,6 +129,12 @@ public: return bytes(); } + eth::LastHashes setCurrentBlockNumber(u256 _currentBlockNumber) + { + m_lastHashes = dev::test::lastHashes(_currentBlockNumber); + return m_lastHashes; + } + private: template auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) @@ -132,7 +153,7 @@ private: void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0) { m_state.addBalance(m_sender, _value); // just in case - eth::Executive executive(m_state, eth::LastHashes(), 0); + eth::Executive executive(m_state, m_lastHashes, 0); eth::Transaction t = _isCreation ? eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) : eth::Transaction(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); bytes transactionRLP = t.rlp(); @@ -170,6 +191,7 @@ protected: u256 const m_gas = 1000000; bytes m_output; eth::LogEntries m_logs; + eth::LastHashes m_lastHashes; }; } From ab4178941b1f1d99bf266cd0a27d79a27162513a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 19 Jan 2015 17:00:23 +0100 Subject: [PATCH 11/24] Adding blockhash test in Solidity ExpressionCompiler --- SolidityExpressionCompiler.cpp | 25 +++++++++++++++++++++++-- solidityExecutionFramework.h | 10 +--------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/SolidityExpressionCompiler.cpp b/SolidityExpressionCompiler.cpp index 579af5bb9..d50dc253e 100644 --- a/SolidityExpressionCompiler.cpp +++ b/SolidityExpressionCompiler.cpp @@ -86,13 +86,19 @@ Declaration const& resolveDeclaration(vector const& _namespacedName, } bytes compileFirstExpression(const string& _sourceCode, vector> _functions = {}, - vector> _localVariables = {}) + vector> _localVariables = {}, vector> _globalDeclarations = {}) { Parser parser; ASTPointer sourceUnit; BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode)))); - NameAndTypeResolver resolver({}); + + vector declarations; + declarations.reserve(_globalDeclarations.size() + 1); + for (ASTPointer const& variable: _globalDeclarations) + declarations.push_back(variable.get()); + NameAndTypeResolver resolver(declarations); resolver.registerDeclarations(*sourceUnit); + for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { @@ -390,6 +396,21 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE(blockhash) +{ + char const* sourceCode = "contract test {\n" + " function f() {\n" + " block.blockhash(3);\n" + " }\n" + "}\n"; + bytes code = compileFirstExpression(sourceCode, {}, {}, + {make_shared("block", make_shared(MagicType::Kind::BLOCK))}); + + bytes expectation({byte(eth::Instruction::PUSH1), 0x03, + byte(eth::Instruction::BLOCKHASH)}); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h index 1160d046f..1aea61fec 100644 --- a/solidityExecutionFramework.h +++ b/solidityExecutionFramework.h @@ -29,7 +29,6 @@ #include #include #include -#include "TestHelper.h" namespace dev { @@ -129,12 +128,6 @@ public: return bytes(); } - eth::LastHashes setCurrentBlockNumber(u256 _currentBlockNumber) - { - m_lastHashes = dev::test::lastHashes(_currentBlockNumber); - return m_lastHashes; - } - private: template auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) @@ -153,7 +146,7 @@ private: void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0) { m_state.addBalance(m_sender, _value); // just in case - eth::Executive executive(m_state, m_lastHashes, 0); + eth::Executive executive(m_state, eth::LastHashes(), 0); eth::Transaction t = _isCreation ? eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) : eth::Transaction(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); bytes transactionRLP = t.rlp(); @@ -191,7 +184,6 @@ protected: u256 const m_gas = 1000000; bytes m_output; eth::LogEntries m_logs; - eth::LastHashes m_lastHashes; }; } From 02521a164ce8fc49d6d4af584da127098c59ba2f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 19 Jan 2015 18:58:09 +0100 Subject: [PATCH 12/24] Improved handling of exceptions in some Solidity Tests --- SolidityABIJSON.cpp | 8 ++------ SolidityNatspecJSON.cpp | 8 ++------ solidityExecutionFramework.h | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/SolidityABIJSON.cpp b/SolidityABIJSON.cpp index d553f576a..892b71f15 100644 --- a/SolidityABIJSON.cpp +++ b/SolidityABIJSON.cpp @@ -41,13 +41,9 @@ public: { m_compilerStack.parse(_code); } - catch (const std::exception& e) + catch(boost::exception const& _e) { - std::string const* extra = boost::get_error_info(e); - std::string msg = std::string("Parsing contract failed with: ") + - e.what() + std::string("\n"); - if (extra) - msg += *extra; + auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e); BOOST_FAIL(msg); } std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE); diff --git a/SolidityNatspecJSON.cpp b/SolidityNatspecJSON.cpp index d43aebc2b..5cec0444c 100644 --- a/SolidityNatspecJSON.cpp +++ b/SolidityNatspecJSON.cpp @@ -45,13 +45,9 @@ public: { m_compilerStack.parse(_code); } - catch (const std::exception& e) + catch(boost::exception const& _e) { - std::string const* extra = boost::get_error_info(e); - std::string msg = std::string("Parsing contract failed with: ") + - e.what() + std::string("\n"); - if (extra) - msg += *extra; + auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e); BOOST_FAIL(msg); } diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h index 1aea61fec..271a594c4 100644 --- a/solidityExecutionFramework.h +++ b/solidityExecutionFramework.h @@ -50,13 +50,9 @@ public: { compiler.compile(_sourceCode, m_optimize); } - catch (const std::exception& e) + catch(boost::exception const& _e) { - std::string const* extra = boost::get_error_info(e); - std::string msg = std::string("Parsing contract failed with: ") + - e.what() + std::string("\n"); - if (extra) - msg += *extra; + auto msg = std::string("Compiling contract failed with: ") + boost::diagnostic_information(_e); BOOST_FAIL(msg); } From ffed2f37cbd6ccde0f58df8e24e801e61c1ae353 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 15 Jan 2015 16:15:01 +0100 Subject: [PATCH 13/24] Inheritance parser. --- SolidityParser.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/SolidityParser.cpp b/SolidityParser.cpp index 86f935c39..f18c530b5 100644 --- a/SolidityParser.cpp +++ b/SolidityParser.cpp @@ -495,6 +495,36 @@ BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(contract_inheritance) +{ + char const* text = "contract base {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n" + "contract derived is base {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(contract_multiple_inheritance) +{ + char const* text = "contract base {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n" + "contract derived is base, nonExisting {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + BOOST_AUTO_TEST_SUITE_END() } From fb41b96bb89d2e250759159f992b460442fa0b06 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 15 Jan 2015 20:04:06 +0100 Subject: [PATCH 14/24] Import inherited members into the contract's scope. --- SolidityNameAndTypeResolution.cpp | 35 ++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index e2b4f160d..f4a1abbd1 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -357,7 +357,6 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) } } - BOOST_AUTO_TEST_CASE(hash_collision_in_interface) { char const* text = "contract test {\n" @@ -369,6 +368,40 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(inheritance_basic) +{ + char const* text = R"( + contract base { uint baseMember; struct BaseType { uint element; } } + contract derived is base { + BaseType data; + function f() { baseMember = 7; } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(inheritance_diamond_basic) +{ + char const* text = R"( + contract root { function rootFunction() {} } + contract inter1 is root { function f() {} } + contract inter2 is root { function f() {} } + contract derived is inter1, inter2, root { + function g() { f(); rootFunction(); } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(cyclic_inheritance) +{ + char const* text = R"( + contract A is B { } + contract B is A { } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } From 580d712a671c8ac576decba34c0a4f2282585a15 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 16 Jan 2015 17:50:10 +0100 Subject: [PATCH 15/24] Check overrides and provide inherited public interface. --- SolidityNameAndTypeResolution.cpp | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index f4a1abbd1..8cc45ce6e 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -402,6 +402,55 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(illegal_override_direct) +{ + char const* text = R"( + contract B { function f() {} } + contract C is B { function f(uint i) {} } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(illegal_override_indirect) +{ + char const* text = R"( + contract A { function f(uint a) {} } + contract B { function f() {} } + contract C is A, B { } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(complex_inheritance) +{ + char const* text = R"( + contract A { function f() { uint8 x = C(0).g(); } } + contract B { function f() {} function g() returns (uint8 r) {} } + contract C is A, B { } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(constructor_visibility) +{ + // The constructor of a base class should not be visible in the derived class + char const* text = R"( + contract A { function A() { } } + contract B is A { function f() { A x = A(0); } } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(overriding_constructor) +{ + // It is fine to "override" constructor of a base class since it is invisible + char const* text = R"( + contract A { function A() { } } + contract B is A { function A() returns (uint8 r) {} } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } From 70cda182f266e70e1cef065a6adb6862373785d5 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 16 Jan 2015 18:52:27 +0100 Subject: [PATCH 16/24] Magic variables are only needed durinng name and type resolution, not during compilation. --- SolidityCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SolidityCompiler.cpp b/SolidityCompiler.cpp index b4874e195..53daa9dfe 100644 --- a/SolidityCompiler.cpp +++ b/SolidityCompiler.cpp @@ -64,7 +64,7 @@ bytes compileContract(const string& _sourceCode) if (ContractDefinition* contract = dynamic_cast(node.get())) { Compiler compiler; - compiler.compileContract(*contract, {}, map{}); + compiler.compileContract(*contract, map{}); // debug //compiler.streamAssembly(cout); From f84d8f2b504332438530abb2456dc2dc809587f6 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 15 Jan 2015 20:04:24 +0100 Subject: [PATCH 17/24] Inheritance in compiler. --- SolidityEndToEndTest.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index dd57a1d15..934b39ad6 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1493,6 +1493,66 @@ BOOST_AUTO_TEST_CASE(value_for_constructor) BOOST_REQUIRE(callContractFunction("getBalances()") == encodeArgs(12, 10)); } +BOOST_AUTO_TEST_CASE(virtual_function_calls) +{ + char const* sourceCode = R"( + contract Base { + function f() returns (uint i) { return g(); } + function g() returns (uint i) { return 1; } + } + contract Derived is Base { + function g() returns (uint i) { return 2; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(2)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(2)); +} + +BOOST_AUTO_TEST_CASE(access_base_storage) +{ + char const* sourceCode = R"( + contract Base { + uint dataBase; + function getViaBase() returns (uint i) { return dataBase; } + } + contract Derived is Base { + uint dataDerived; + function setData(uint base, uint derived) returns (bool r) { + dataBase = base; + dataDerived = derived; + return true; + } + function getViaDerived() returns (uint base, uint derived) { + base = dataBase; + derived = dataDerived; + } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("setData(uint256,uint256)", 1, 2) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("getViaBase()") == encodeArgs(1)); + BOOST_CHECK(callContractFunction("getViaDerived()") == encodeArgs(1, 2)); +} + +BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) +{ + char const* sourceCode = R"( + contract Base { + uint data; + function setData(uint i) { data = i; } + function getViaBase() returns (uint i) { return data; } + } + contract A is Base { function setViaA(uint i) { setData(i); } } + contract B is Base { function getViaB() returns (uint i) { return getViaBase(); } } + contract Derived is A, B, Base { } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("setViaA(uint256)", 23) == encodeArgs()); + BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(23)); +} + BOOST_AUTO_TEST_SUITE_END() } From 2e846c495b737b7d300fbf92b05881b4acb4ea36 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 19 Jan 2015 19:18:34 +0100 Subject: [PATCH 18/24] Explicit calls to base class function. --- SolidityEndToEndTest.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 934b39ad6..0f61d2851 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1553,6 +1553,21 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(23)); } +BOOST_AUTO_TEST_CASE(explicit_base_cass) +{ + char const* sourceCode = R"( + contract BaseBase { function g() returns (uint r) { return 1; } } + contract Base is BaseBase { function g() returns (uint r) { return 2; } } + contract Derived is Base { + function f() returns (uint r) { return BaseBase.g(); } + function g() returns (uint r) { return 3; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(3)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(1)); +} + BOOST_AUTO_TEST_SUITE_END() } From fe770957c68007ccf86eddb639b596e78fd7b9ba Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 19 Jan 2015 21:05:47 +0100 Subject: [PATCH 19/24] Constructor arguments for base classes. --- SolidityParser.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/SolidityParser.cpp b/SolidityParser.cpp index f18c530b5..91e571306 100644 --- a/SolidityParser.cpp +++ b/SolidityParser.cpp @@ -525,6 +525,21 @@ BOOST_AUTO_TEST_CASE(contract_multiple_inheritance) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments) +{ + char const* text = "contract base {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n" + "contract derived is base(2), nonExisting(\"abc\", \"def\", base.fun()) {\n" + " function fun() {\n" + " uint64(2);\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + BOOST_AUTO_TEST_SUITE_END() } From 961cb5b90c70534df3704c2a905fa0b42f35bfbd Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 19 Jan 2015 23:08:48 +0100 Subject: [PATCH 20/24] Call constructors of base classes. --- SolidityEndToEndTest.cpp | 60 +++++++++++++++++++++++++++++++ SolidityNameAndTypeResolution.cpp | 18 ++++++++++ 2 files changed, 78 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 0f61d2851..cba926d6d 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1568,6 +1568,66 @@ BOOST_AUTO_TEST_CASE(explicit_base_cass) BOOST_CHECK(callContractFunction("f()") == encodeArgs(1)); } +BOOST_AUTO_TEST_CASE(base_constructor_arguments) +{ + char const* sourceCode = R"( + contract BaseBase { + uint m_a; + function BaseBase(uint a) { + m_a = a; + } + } + contract Base is BaseBase(7) { + function Base() { + m_a *= m_a; + } + } + contract Derived is Base() { + function getA() returns (uint r) { return m_a; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("getA()") == encodeArgs(7 * 7)); +} + +BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) +{ + char const* sourceCode = R"( + contract BaseBase { + uint m_a; + function BaseBase(uint a) { + m_a = a; + } + function g() returns (uint r) { return 2; } + } + contract Base is BaseBase(BaseBase.g()) { + } + contract Derived is Base() { + function getA() returns (uint r) { return m_a; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); +} + +BOOST_AUTO_TEST_CASE(constructor_argument_overriding) +{ + char const* sourceCode = R"( + contract BaseBase { + uint m_a; + function BaseBase(uint a) { + m_a = a; + } + } + contract Base is BaseBase(2) { } + contract Derived is Base, BaseBase(3) { + function getA() returns (uint r) { return m_a; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("getA()") == encodeArgs(3)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 8cc45ce6e..c0ebb0eda 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -451,6 +451,24 @@ BOOST_AUTO_TEST_CASE(overriding_constructor) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments) +{ + char const* text = R"( + contract A { function A(uint a) { } } + contract B is A { } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) +{ + char const* text = R"( + contract A { function A(uint a) { } } + contract B is A { } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } From 609268ee624a2ea6af4ed11a9830272faf6082bb Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 19 Jan 2015 23:34:49 +0100 Subject: [PATCH 21/24] Implicit conversion from derived to base. --- SolidityNameAndTypeResolution.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index c0ebb0eda..6c8fd1b1c 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -469,6 +469,27 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion) +{ + char const* text = R"( + contract A { } + contract B is A { + function f() { A a = B(1); } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} +BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) +{ + char const* text = R"( + contract A { } + contract B is A { + function f() { B b = A(1); } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } From 8b29bdaf1067d757a253f5e3e604e1b42e28d579 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 20 Jan 2015 13:15:43 +0100 Subject: [PATCH 22/24] Absence of tag in Natspec is now considered @notice --- SolidityNatspecJSON.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/SolidityNatspecJSON.cpp b/SolidityNatspecJSON.cpp index 5cec0444c..743651d54 100644 --- a/SolidityNatspecJSON.cpp +++ b/SolidityNatspecJSON.cpp @@ -506,17 +506,35 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error) BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); } -// test for bug where having no tags in docstring would cause infinite loop -BOOST_AUTO_TEST_CASE(natspec_no_tags) +BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) { char const* sourceCode = "contract test {\n" " /// I do something awesome\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" "}\n"; - char const* natspec = "{\"methods\": {}}"; + char const* natspec = "{" + "\"methods\":{" + " \"mul(uint256)\":{ \"notice\": \"I do something awesome\"}" + "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, natspec, true); +} + +BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) +{ + char const* sourceCode = "contract test {\n" + " /// I do something awesome\n" + " /// which requires two lines to explain\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul(uint256)\":{ \"notice\": \"I do something awesome which requires two lines to explain\"}" + "}}"; + + checkNatspec(sourceCode, natspec, true); } BOOST_AUTO_TEST_SUITE_END() From 3ff1c3ec30b013dcd2ba58ebe3277c1c44eb759b Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 20 Jan 2015 15:58:04 +0100 Subject: [PATCH 23/24] Include virtual function overrides in constructor context. --- SolidityEndToEndTest.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index cba926d6d..cf04edaad 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1610,6 +1610,28 @@ BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) +{ + char const* sourceCode = R"( + contract BaseBase { + uint m_a; + function BaseBase(uint a) { + m_a = a; + } + function overridden() returns (uint r) { return 1; } + function g() returns (uint r) { return overridden(); } + } + contract Base is BaseBase(BaseBase.g()) { + } + contract Derived is Base() { + function getA() returns (uint r) { return m_a; } + function overridden() returns (uint r) { return 2; } + } + )"; + compileAndRun(sourceCode, 0, "Derived"); + BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); +} + BOOST_AUTO_TEST_CASE(constructor_argument_overriding) { char const* sourceCode = R"( From 5f54782ed090d62a241bf5a70d52b48a9e217336 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 20 Jan 2015 11:33:33 -0800 Subject: [PATCH 24/24] Cleanups and addition AZ info. --- TestHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestHelper.cpp b/TestHelper.cpp index 355a5080d..45c56f6ae 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -115,7 +115,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state) if (code.size()) { _state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception); - _state.m_cache[address].setCode(bytesConstRef(&code)); + _state.m_cache[address].setCode(code); } else _state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation);