From 5234408ff507519e4e6d5e9eef8f76bd9b322b64 Mon Sep 17 00:00:00 2001 From: bernard peh Date: Sat, 16 Sep 2017 23:13:50 +1000 Subject: [PATCH 001/108] possible typo fix --- docs/frequently-asked-questions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index f59d86e7ece0..5df5313c1696 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -305,7 +305,7 @@ of variable it concerns: * state variables are always in storage * function arguments are always in memory -* local variables always reference storage +* local variables are always in stack Example:: From 06e828542b12c68ebba1c19a4c6d12e7b44d0bab Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 21 Sep 2017 18:19:33 +0200 Subject: [PATCH 002/108] Increment version. --- CMakeLists.txt | 2 +- Changelog.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 139d4fd5dbb6..8f71cedce7de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.17") +set(PROJECT_VERSION "0.4.18") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) diff --git a/Changelog.md b/Changelog.md index bdd6ac468db9..3d185ccb1876 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +### 0.4.18 (unreleased) + +Features: + +Bugfixes: + ### 0.4.17 (2017-09-21) Features: From 2530223ab5c470c01b7e684f33e1fdfa5f5f9590 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 18 Sep 2017 14:47:46 +0200 Subject: [PATCH 003/108] More verbose errors for generated assembly. --- libsolidity/codegen/CompilerContext.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 5a77162eeeee..d87c7be5c1ec 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -312,8 +313,23 @@ void CompilerContext::appendInlineAssembly( ErrorReporter errorReporter(errors); auto scanner = make_shared(CharStream(_assembly), "--CODEGEN--"); auto parserResult = assembly::Parser(errorReporter).parse(scanner); - solAssert(parserResult, "Failed to parse inline assembly block."); - solAssert(errorReporter.errors().empty(), "Failed to parse inline assembly block."); + if (!parserResult || !errorReporter.errors().empty()) + { + string message = + "Error parsing inline assembly block:\n" + "------------------ Input: -----------------\n" + + _assembly + "\n" + "------------------ Errors: ----------------\n"; + for (auto const& error: errorReporter.errors()) + message += SourceReferenceFormatter::formatExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error", + [&](string const&) -> Scanner const& { return *scanner; } + ); + message += "-------------------------------------------\n"; + + solAssert(false, message); + } assembly::AsmAnalysisInfo analysisInfo; assembly::AsmAnalyzer analyzer(analysisInfo, errorReporter, false, identifierAccess.resolve); From f28d40ef0b58ef502ad39d7c953b50fc50430b5e Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 19 Sep 2017 10:25:01 +0200 Subject: [PATCH 004/108] Provide template for whiskers error. --- libdevcore/Whiskers.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libdevcore/Whiskers.cpp b/libdevcore/Whiskers.cpp index b0a4c755e2a9..a6db35c8ed78 100644 --- a/libdevcore/Whiskers.cpp +++ b/libdevcore/Whiskers.cpp @@ -90,7 +90,13 @@ string Whiskers::replace( string tagName(_match[1]); if (!tagName.empty()) { - assertThrow(_parameters.count(tagName), WhiskersError, "Value for tag " + tagName + " not provided."); + assertThrow( + _parameters.count(tagName), + WhiskersError, + "Value for tag " + tagName + " not provided.\n" + + "Template:\n" + + _template + ); return _parameters.at(tagName); } else From a844bbda48564d65033522a64cef30bff5dea973 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 20 Sep 2017 11:52:41 +0200 Subject: [PATCH 005/108] Cleanup test helper macros. --- test/TestHelper.h | 74 ------------------- test/contracts/AuctionRegistrar.cpp | 2 +- test/contracts/FixedFeeRegistrar.cpp | 2 +- test/contracts/Wallet.cpp | 2 +- test/libsolidity/GasMeter.cpp | 2 +- test/libsolidity/Metadata.cpp | 8 +- test/libsolidity/SolidityABIJSON.cpp | 2 +- .../SolidityExpressionCompiler.cpp | 2 +- test/libsolidity/SolidityNatspecJSON.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 22 +++--- 10 files changed, 22 insertions(+), 96 deletions(-) diff --git a/test/TestHelper.h b/test/TestHelper.h index 3e74b54c5bd7..d50568ad9e59 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -15,8 +15,6 @@ along with solidity. If not, see . */ /** @file TestHelper.h - * @author Marko Simovic - * @date 2014 */ #pragma once @@ -31,78 +29,6 @@ namespace dev namespace test { -#if (BOOST_VERSION >= 105900) -#define ETH_BOOST_CHECK_IMPL(_message, _requireOrCheck) BOOST_TEST_TOOL_DIRECT_IMPL( \ - false, \ - _requireOrCheck, \ - _message \ - ) -#else -#define ETH_BOOST_CHECK_IMPL(_message, _requireOrCheck) BOOST_CHECK_IMPL( \ - false, \ - _message, \ - _requireOrCheck, \ - CHECK_MSG \ - ) -#endif - -/// Make sure that no Exception is thrown during testing. If one is thrown show its info and fail the test. -/// Our version of BOOST_REQUIRE_NO_THROW() -/// @param _statement The statement for which to make sure no exceptions are thrown -/// @param _message A message to act as a prefix to the expression's error information -#define ETH_TEST_REQUIRE_NO_THROW(_statement, _message) \ - do \ - { \ - try \ - { \ - BOOST_TEST_PASSPOINT(); \ - _statement; \ - } \ - catch (boost::exception const& _e) \ - { \ - auto msg = std::string(_message " due to an exception thrown by " \ - BOOST_STRINGIZE(_statement) "\n") + boost::diagnostic_information(_e); \ - ETH_BOOST_CHECK_IMPL(msg, REQUIRE); \ - } \ - catch (...) \ - { \ - ETH_BOOST_CHECK_IMPL( \ - "Unknown exception thrown by " BOOST_STRINGIZE(_statement), \ - REQUIRE \ - ); \ - } \ - } \ - while (0) - -/// Check if an Exception is thrown during testing. If one is thrown show its info and continue the test -/// Our version of BOOST_CHECK_NO_THROW() -/// @param _statement The statement for which to make sure no exceptions are thrown -/// @param _message A message to act as a prefix to the expression's error information -#define ETH_TEST_CHECK_NO_THROW(_statement, _message) \ - do \ - { \ - try \ - { \ - BOOST_TEST_PASSPOINT(); \ - _statement; \ - } \ - catch (boost::exception const& _e) \ - { \ - auto msg = std::string(_message " due to an exception thrown by " \ - BOOST_STRINGIZE(_statement) "\n") + boost::diagnostic_information(_e); \ - ETH_BOOST_CHECK_IMPL(msg, CHECK); \ - } \ - catch (...) \ - { \ - ETH_BOOST_CHECK_IMPL( \ - "Unknown exception thrown by " BOOST_STRINGIZE(_statement), \ - CHECK \ - ); \ - } \ - } \ - while (0) - - struct Options: boost::noncopyable { std::string ipcPath; diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index d56edc5622ad..73a5d1ed0c5c 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -223,7 +223,7 @@ class AuctionRegistrarTestFramework: public SolidityExecutionFramework m_compiler.reset(false); m_compiler.addSource("", registrarCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("GlobalRegistrar").bytecode)); } sendMessage(*s_compiledRegistrar, true); diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 967d60b6969b..8327999daad9 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -136,7 +136,7 @@ class RegistrarTestFramework: public SolidityExecutionFramework m_compiler.reset(false); m_compiler.addSource("", registrarCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode)); } sendMessage(*s_compiledRegistrar, true); diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index d12b7493729a..bbe603d4a89b 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -451,7 +451,7 @@ class WalletTestFramework: public SolidityExecutionFramework m_compiler.reset(false); m_compiler.addSource("", walletCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledWallet.reset(new bytes(m_compiler.object("Wallet").bytecode)); } bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners); diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index df9afaaef5af..b759678fe1b6 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -50,7 +50,7 @@ class GasMeterTestFramework: public SolidityExecutionFramework m_compiler.reset(false); m_compiler.addSource("", "pragma solidity >=0.0;\n" + _sourceCode); m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); AssemblyItems const* items = m_compiler.runtimeAssemblyItems(""); ASTNode const& sourceUnit = m_compiler.ast(); diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index c46e31605126..efe8fafffe9b 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); BOOST_CHECK(dev::test::isValidMetadata(metadata)); @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); BOOST_CHECK(dev::test::isValidMetadata(metadata)); @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) )"; compilerStack.addSource("B", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); BOOST_CHECK(dev::test::isValidMetadata(serialisedMetadata)); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) )"; compilerStack.addSource("C", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); BOOST_CHECK(dev::test::isValidMetadata(serialisedMetadata)); diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index e5d9e99c13cb..42f7525f1675 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -44,7 +44,7 @@ class JSONInterfaceChecker { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); - ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); + BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedInterface = m_compilerStack.contractABI(""); Json::Value expectedInterface; diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 58efa0a2eb62..677473866374 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -125,7 +125,7 @@ bytes compileFirstExpression( for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { - ETH_TEST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract), "Resolving names failed"); + BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*contract), "Resolving names failed"); inheritanceHierarchy = vector(1, contract); } for (ASTPointer const& node: sourceUnit->nodes()) diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 149221d5abe4..d83773bc077b 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -47,7 +47,7 @@ class DocumentationChecker { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); - ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); + BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedDocumentation; if (_userDocumentation) diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 60ca03c9789f..a8698d13849a 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -250,7 +250,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) FunctionDefinition const* function = nullptr; auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function"); } @@ -268,7 +268,7 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) ErrorList errors; ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(function->documentation() == nullptr, "Should not have gotten a Natspecc comment for this function"); } @@ -294,17 +294,17 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 1"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(1), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(1), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 2"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(2), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(2), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(function->documentation() == nullptr, "Should not have gotten natspec comment for functionName3()"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(3), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(3), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 4"); } @@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) ErrorList errors; ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function\n" " and it has 2 lines"); } @@ -351,10 +351,10 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "fun1 description"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(1), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(1), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function\n" " and it has 2 lines"); } @@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(!function->documentation(), "Shouldn't get natspec docstring for this function"); } @@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) ASTPointer contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(!function->documentation(), "Shouldn't get natspec docstring for this function"); } From 5ffd119990b300fb4fa3c0cf693c07ed67bb0aa1 Mon Sep 17 00:00:00 2001 From: bernard peh Date: Mon, 25 Sep 2017 19:29:10 +1000 Subject: [PATCH 006/108] minor tuning to sentence to be more accurate --- docs/frequently-asked-questions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 5df5313c1696..387f16fe8f13 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -305,7 +305,7 @@ of variable it concerns: * state variables are always in storage * function arguments are always in memory -* local variables are always in stack +* local variables are always in the stack but reference storage Example:: From 0099911ace631789ab8a2294710b9fd57af1c478 Mon Sep 17 00:00:00 2001 From: wadeAlexC Date: Thu, 21 Sep 2017 17:42:34 -0400 Subject: [PATCH 007/108] Better error message for unexpected trailing comma in parameter lists --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 2 + test/libsolidity/SolidityParser.cpp | 84 +++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/Changelog.md b/Changelog.md index 3d185ccb1876..9755d2d361af 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.18 (unreleased) Features: + * Parser: Better error message for unexpected trailing comma in parameter lists. Bugfixes: diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ce8a9f0113f4..9a8bb3585ba5 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -828,6 +828,8 @@ ASTPointer Parser::parseParameterList( parameters.push_back(parseVariableDeclaration(options)); while (m_scanner->currentToken() != Token::RParen) { + if (m_scanner->currentToken() == Token::Comma && m_scanner->peekNextToken() == Token::RParen) + fatalParserError("Unexpected trailing comma in parameter list."); expectToken(Token::Comma); parameters.push_back(parseVariableDeclaration(options)); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index a8698d13849a..72473c3e6aec 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -167,6 +167,90 @@ BOOST_AUTO_TEST_CASE(single_function_param) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(single_function_param_trailing_comma) +{ + char const* text = R"( + contract test { + function(uint a,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_return_param_trailing_comma) +{ + char const* text = R"( + contract test { + function() returns (uint a,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_modifier_arg_trailing_comma) +{ + char const* text = R"( + contract test { + modifier modTest(uint a,) { _; } + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_event_arg_trailing_comma) +{ + char const* text = R"( + contract test { + event Test(uint a,); + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(multiple_function_param_trailing_comma) +{ + char const* text = R"( + contract test { + function(uint a, uint b,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(multiple_return_param_trailing_comma) +{ + char const* text = R"( + contract test { + function() returns (uint a, uint b,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(multiple_modifier_arg_trailing_comma) +{ + char const* text = R"( + contract test { + modifier modTest(uint a, uint b,) { _; } + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(multiple_event_arg_trailing_comma) +{ + char const* text = R"( + contract test { + event Test(uint a, uint b,); + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + BOOST_AUTO_TEST_CASE(function_no_body) { char const* text = R"( From 8e4f242274caf874e3ebdf6d65dcfae3529f2c6b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 20 Sep 2017 14:23:00 +0200 Subject: [PATCH 008/108] Improved error messages for EndToEnd tests. --- test/ExecutionFramework.cpp | 28 + test/ExecutionFramework.h | 8 + test/libsolidity/SolidityEndToEndTest.cpp | 1670 +++++++++-------- test/libsolidity/SolidityExecutionFramework.h | 2 +- 4 files changed, 884 insertions(+), 824 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index b2de814a9838..85b5bd3bb8f7 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -25,6 +25,8 @@ #include #include +#include + using namespace std; using namespace dev; using namespace dev::test; @@ -54,6 +56,32 @@ ExecutionFramework::ExecutionFramework() : m_rpc.test_rewindToBlock(0); } +std::pair ExecutionFramework::compareAndCreateMessage( + bytes const& _result, + bytes const& _expectation +) +{ + if (_result == _expectation) + return std::make_pair(true, std::string{}); + std::string message = + "Invalid encoded data\n" + " Result Expectation\n"; + auto resultHex = boost::replace_all_copy(toHex(_result), "0", "."); + auto expectedHex = boost::replace_all_copy(toHex(_expectation), "0", "."); + for (size_t i = 0; i < std::max(resultHex.size(), expectedHex.size()); i += 0x40) + { + std::string result{i >= resultHex.size() ? string{} : resultHex.substr(i, 0x40)}; + std::string expected{i > expectedHex.size() ? string{} : expectedHex.substr(i, 0x40)}; + message += + (result == expected ? " " : " X ") + + result + + std::string(0x41 - result.size(), ' ') + + expected + + "\n"; + } + return make_pair(false, message); +} + void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) { if (m_showMessages) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index e8d8d111c2c8..cc25bea737b9 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -131,6 +131,8 @@ class ExecutionFramework } } + static std::pair compareAndCreateMessage(bytes const& _result, bytes const& _expectation); + static bytes encode(bool _value) { return encode(byte(_value)); } static bytes encode(int _value) { return encode(u256(_value)); } static bytes encode(size_t _value) { return encode(u256(_value)); } @@ -293,6 +295,12 @@ class ExecutionFramework u256 m_gasUsed; }; +#define ABI_CHECK(result, expectation) do { \ + auto abiCheckResult = ExecutionFramework::compareAndCreateMessage((result), (expectation)); \ + BOOST_CHECK_MESSAGE(abiCheckResult.first, abiCheckResult.second); \ +} while (0) + + } } // end namespaces diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 458b64f40ab1..82dedf853a43 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(8))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(8))); } BOOST_AUTO_TEST_CASE(exp_operator_const_signed) @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(-8))); } BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(5))); } BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(10))); } BOOST_AUTO_TEST_CASE(conditional_expression_multiple) @@ -134,10 +134,10 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(80)) == toBigEndian(u256(50))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(40)) == toBigEndian(u256(10))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1001)), toBigEndian(u256(1000))); + ABI_CHECK(callContractFunction("f(uint256)", u256(500)), toBigEndian(u256(100))); + ABI_CHECK(callContractFunction("f(uint256)", u256(80)), toBigEndian(u256(50))); + ABI_CHECK(callContractFunction("f(uint256)", u256(40)), toBigEndian(u256(10))); } BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) @@ -149,8 +149,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0))); - BOOST_CHECK(callContractFunction("f(bool,uint256)", false, u256(20)) == encodeArgs(u256(0), u256(20))); + ABI_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)), encodeArgs(u256(20), u256(0))); + ABI_CHECK(callContractFunction("f(bool,uint256)", false, u256(20)), encodeArgs(u256(0), u256(20))); } BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) @@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) @@ -216,8 +216,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(conditional_expression_different_types) @@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(0xcd))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(0xabab))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(0xcd))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(0xabab))); } /* let's add this back when I figure out the correct type conversion. @@ -247,8 +247,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_string_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(string("true", 4))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(string("false", 5))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(string("true", 4))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(string("false", 5))); } */ @@ -262,8 +262,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(3), u256(4))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(conditional_expression_functions) @@ -280,8 +280,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(recursive_calls) @@ -317,11 +317,11 @@ BOOST_AUTO_TEST_CASE(multiple_functions) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("a()", bytes()) == toBigEndian(u256(0))); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(1))); - BOOST_CHECK(callContractFunction("c()", bytes()) == toBigEndian(u256(2))); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(3))); - BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes()); + ABI_CHECK(callContractFunction("a()", bytes()), toBigEndian(u256(0))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(1))); + ABI_CHECK(callContractFunction("c()", bytes()), toBigEndian(u256(2))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(3))); + ABI_CHECK(callContractFunction("i_am_not_there()", bytes()), bytes()); } BOOST_AUTO_TEST_CASE(named_args) @@ -333,7 +333,7 @@ BOOST_AUTO_TEST_CASE(named_args) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(disorder_named_args) @@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(disorder_named_args) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(while_loop) @@ -665,8 +665,10 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")) - == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); + ABI_CHECK( + callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")), + fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f") + ); } BOOST_AUTO_TEST_CASE(packing_signed_types) @@ -680,8 +682,10 @@ BOOST_AUTO_TEST_CASE(packing_signed_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run()") - == fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa")); + ABI_CHECK( + callContractFunction("run()"), + fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa") + ); } BOOST_AUTO_TEST_CASE(multiple_return_values) @@ -694,7 +698,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd) == encodeArgs(0xcd, true, 0)); + ABI_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd), encodeArgs(0xcd, true, 0)); } BOOST_AUTO_TEST_CASE(short_circuiting) @@ -816,8 +820,8 @@ BOOST_AUTO_TEST_CASE(strings) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("fixedBytes()") == encodeArgs(string("abc\0\xff__", 7))); - BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); + ABI_CHECK(callContractFunction("fixedBytes()"), encodeArgs(string("abc\0\xff__", 7))); + ABI_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true), encodeArgs(string("\0\x2", 2), true)); } BOOST_AUTO_TEST_CASE(inc_dec_operators) @@ -838,7 +842,7 @@ BOOST_AUTO_TEST_CASE(inc_dec_operators) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0x53866)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x53866)); } BOOST_AUTO_TEST_CASE(bytes_comparison) @@ -854,7 +858,7 @@ BOOST_AUTO_TEST_CASE(bytes_comparison) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(state_smoke_test) @@ -874,14 +878,14 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x1234) == encodeArgs()); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x01), 0x8765) == encodeArgs()); - BOOST_CHECK(callContractFunction("get(uint8)", byte( 0x00)) == encodeArgs(0x1234)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0x8765)); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x3) == encodeArgs()); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0x3)); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(0)); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(0)); + ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x1234), encodeArgs()); + ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x01), 0x8765), encodeArgs()); + ABI_CHECK(callContractFunction("get(uint8)", byte( 0x00)), encodeArgs(0x1234)); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(0x8765)); + ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x3), encodeArgs()); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(0x3)); } BOOST_AUTO_TEST_CASE(compound_assign) @@ -936,21 +940,21 @@ BOOST_AUTO_TEST_CASE(simple_mapping) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0)), encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); callContractFunction("set(uint8,uint8)", byte(0x01), byte(0xa1)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0xa1))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0xa1))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); callContractFunction("set(uint8,uint8)", byte(0x00), byte(0xef)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0xef))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0xa1))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0xef))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0xa1))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); callContractFunction("set(uint8,uint8)", byte(0x01), byte(0x05)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0xef))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x05))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0xef))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0x05))); + ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); } BOOST_AUTO_TEST_CASE(mapping_state) @@ -1126,9 +1130,9 @@ BOOST_AUTO_TEST_CASE(structs) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("set()") == bytes()); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("set()"), bytes()); + ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(struct_reference) @@ -1156,9 +1160,9 @@ BOOST_AUTO_TEST_CASE(struct_reference) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("set()") == bytes()); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("set()"), bytes()); + ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(deleteStruct) @@ -1209,14 +1213,14 @@ BOOST_AUTO_TEST_CASE(deleteStruct) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("getToDelete()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("getTopValue()"), encodeArgs(0)); + ABI_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)); + ABI_CHECK(callContractFunction("getTopMapping(uint256)", 0), encodeArgs(1)); + ABI_CHECK(callContractFunction("getTopMapping(uint256)", 1), encodeArgs(2)); + ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 0), encodeArgs(true)); + ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 1), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(deleteLocal) @@ -1231,7 +1235,7 @@ BOOST_AUTO_TEST_CASE(deleteLocal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(deleteLocals) @@ -1249,7 +1253,7 @@ BOOST_AUTO_TEST_CASE(deleteLocals) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7)); + ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(6, 7)); } BOOST_AUTO_TEST_CASE(constructor) @@ -1287,7 +1291,7 @@ BOOST_AUTO_TEST_CASE(simple_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); + ABI_CHECK(callContractFunction("data()"), encodeArgs(8)); } BOOST_AUTO_TEST_CASE(array_accessor) @@ -1314,14 +1318,14 @@ BOOST_AUTO_TEST_CASE(array_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256)", 0) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("dynamicData(uint256)", 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 1) == encodeArgs(22)); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 127) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 128) == encodeArgs()); - BOOST_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2) == encodeArgs(3)); + ABI_CHECK(callContractFunction("data(uint256)", 0), encodeArgs(8)); + ABI_CHECK(callContractFunction("data(uint256)", 8), encodeArgs()); + ABI_CHECK(callContractFunction("dynamicData(uint256)", 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("dynamicData(uint256)", 8), encodeArgs()); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 1), encodeArgs(22)); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 127), encodeArgs(2)); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 128), encodeArgs()); + ABI_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) @@ -1338,10 +1342,10 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("data(uint256, 256)", 2, 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8) == encodeArgs()); + ABI_CHECK(callContractFunction("data(uint256,uint256)", 2, 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("data(uint256, 256)", 2, 8), encodeArgs()); + ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8), encodeArgs()); } BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) @@ -1363,11 +1367,11 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); - BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::keccak256(bytes(1, 0x7b)))); - BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); - BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); + ABI_CHECK(callContractFunction("data()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("name()"), encodeArgs("Celina")); + ABI_CHECK(callContractFunction("a_hash()"), encodeArgs(dev::keccak256(bytes(1, 0x7b)))); + ABI_CHECK(callContractFunction("an_address()"), encodeArgs(toBigEndian(u160(0x1337)))); + ABI_CHECK(callContractFunction("super_secret_data()"), bytes()); } BOOST_AUTO_TEST_CASE(complex_accessors) @@ -1387,10 +1391,10 @@ BOOST_AUTO_TEST_CASE(complex_accessors) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24")); - BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false)); - BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12)); - BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31)); + ABI_CHECK(callContractFunction("to_string_map(uint256)", 42), encodeArgs("24")); + ABI_CHECK(callContractFunction("to_bool_map(uint256)", 42), encodeArgs(false)); + ABI_CHECK(callContractFunction("to_uint_map(uint256)", 42), encodeArgs(12)); + ABI_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23), encodeArgs(31)); } BOOST_AUTO_TEST_CASE(struct_accessor) @@ -1408,7 +1412,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256)", 7) == encodeArgs(1, 2, true)); + ABI_CHECK(callContractFunction("data(uint256)", 7), encodeArgs(1, 2, true)); } BOOST_AUTO_TEST_CASE(balance) @@ -1422,7 +1426,7 @@ BOOST_AUTO_TEST_CASE(balance) } )"; compileAndRun(sourceCode, 23); - BOOST_CHECK(callContractFunction("getBalance()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("getBalance()"), encodeArgs(23)); } BOOST_AUTO_TEST_CASE(blockchain) @@ -1440,7 +1444,7 @@ BOOST_AUTO_TEST_CASE(blockchain) BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true); m_rpc.test_mineBlocks(5); compileAndRun(sourceCode, 27); - BOOST_CHECK(callContractFunctionWithValue("someInfo()", 28) == encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7)); + ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7)); } BOOST_AUTO_TEST_CASE(msg_sig) @@ -1453,7 +1457,7 @@ BOOST_AUTO_TEST_CASE(msg_sig) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) @@ -1469,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(now) @@ -1518,7 +1522,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("ab")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd"), encodeArgs("ab")); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) @@ -1531,7 +1535,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab") == encodeArgs("ab")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab"), encodeArgs("ab")); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) @@ -1544,7 +1548,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("abcd")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd"), encodeArgs("abcd")); } // fixed bytes to uint conversion tests @@ -1558,8 +1562,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) == - encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes32)", string("abc2")), + encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) @@ -1572,8 +1578,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) == - encodeArgs(u256("0x61"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes1)", string("a")), + encodeArgs(u256("0x61")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) @@ -1586,8 +1594,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == - encodeArgs(u256("0x6364"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes4)", string("abcd")), + encodeArgs(u256("0x6364")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) @@ -1600,8 +1610,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == - encodeArgs(u256("0x61626364"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes4)", string("abcd")), + encodeArgs(u256("0x61626364")) + ); } // uint fixed bytes conversion tests @@ -1616,7 +1628,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) )"; compileAndRun(sourceCode); u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a)); + ABI_CHECK(callContractFunction("uintToBytes(uint256)", a), encodeArgs(a)); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) @@ -1629,8 +1641,10 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) == - encodeArgs(string("a"))); + ABI_CHECK( + callContractFunction("UintToBytes(uint8)", u256("0x61")), + encodeArgs(string("a")) + ); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) @@ -1643,8 +1657,10 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("uintToBytes(uint32)", - u160("0x61626364")) == encodeArgs(string("cd"))); + ABI_CHECK( + callContractFunction("uintToBytes(uint32)", u160("0x61626364")), + encodeArgs(string("cd")) + ); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) @@ -1657,8 +1673,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK( - callContractFunction("UintToBytes(uint16)", u256("0x6162")) == + ABI_CHECK( + callContractFunction("UintToBytes(uint16)", u256("0x6162")), encodeArgs(string("\0\0\0\0\0\0ab", 8)) ); } @@ -1677,7 +1693,7 @@ BOOST_AUTO_TEST_CASE(send_ether) u256 amount(130); compileAndRun(sourceCode, amount + 1); u160 address(23); - BOOST_CHECK(callContractFunction("a(address,uint256)", address, amount) == encodeArgs(1)); + ABI_CHECK(callContractFunction("a(address,uint256)", address, amount), encodeArgs(1)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -1710,11 +1726,11 @@ BOOST_AUTO_TEST_CASE(transfer_ether) u160 const oogRecipient = m_contractAddress; compileAndRun(sourceCode, 20, "A"); u160 payableRecipient(23); - BOOST_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10) == encodeArgs(10)); + ABI_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10), encodeArgs(10)); BOOST_CHECK_EQUAL(balanceAt(payableRecipient), 10); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); - BOOST_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10) == encodeArgs()); - BOOST_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10) == encodeArgs()); + ABI_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10), encodeArgs()); + ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs()); } BOOST_AUTO_TEST_CASE(log0) @@ -1840,7 +1856,7 @@ BOOST_AUTO_TEST_CASE(suicide) u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); - BOOST_CHECK(callContractFunction("a(address)", address) == bytes()); + ABI_CHECK(callContractFunction("a(address)", address), bytes()); BOOST_CHECK(!addressHasCode(m_contractAddress)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -1859,7 +1875,7 @@ BOOST_AUTO_TEST_CASE(selfdestruct) u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); - BOOST_CHECK(callContractFunction("a(address)", address) == bytes()); + ABI_CHECK(callContractFunction("a(address)", address), bytes()); BOOST_CHECK(!addressHasCode(m_contractAddress)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -2046,7 +2062,7 @@ BOOST_AUTO_TEST_CASE(ecrecover) u256 r("0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"); u256 s("0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"); u160 addr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); - BOOST_CHECK(callContractFunction("a(bytes32,uint8,bytes32,bytes32)", h, v, r, s) == encodeArgs(addr)); + ABI_CHECK(callContractFunction("a(bytes32,uint8,bytes32,bytes32)", h, v, r, s), encodeArgs(addr)); } BOOST_AUTO_TEST_CASE(inter_contract_calls) @@ -2231,7 +2247,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls) compileAndRun(sourceCode, 0, "Main"); BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes()); BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress)); - BOOST_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true) == encodeArgs(string("\0a\0\0\0", 5))); + ABI_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true), encodeArgs(string("\0a\0\0\0", 5))); } BOOST_AUTO_TEST_CASE(constructor_arguments_internal) @@ -2257,8 +2273,8 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_internal) function getName() returns (bytes3 ret) { return h.getName(); } })"; compileAndRun(sourceCode, 0, "Main"); - BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); + ABI_CHECK(callContractFunction("getFlag()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("getName()"), encodeArgs("abc")); } BOOST_AUTO_TEST_CASE(constructor_arguments_external) @@ -2277,8 +2293,8 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_external) } )"; compileAndRun(sourceCode, 0, "Main", encodeArgs("abc", true)); - BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); + ABI_CHECK(callContractFunction("getFlag()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("getName()"), encodeArgs("abc")); } BOOST_AUTO_TEST_CASE(constructor_with_long_arguments) @@ -2305,8 +2321,8 @@ BOOST_AUTO_TEST_CASE(constructor_with_long_arguments) u256(b.length()), b )); - BOOST_CHECK(callContractFunction("a()") == encodeDyn(a)); - BOOST_CHECK(callContractFunction("b()") == encodeDyn(b)); + ABI_CHECK(callContractFunction("a()"), encodeDyn(a)); + ABI_CHECK(callContractFunction("b()"), encodeDyn(b)); } BOOST_AUTO_TEST_CASE(constructor_static_array_argument) @@ -2323,10 +2339,10 @@ BOOST_AUTO_TEST_CASE(constructor_static_array_argument) } )"; compileAndRun(sourceCode, 0, "C", encodeArgs(u256(1), u256(2), u256(3), u256(4))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(0)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(1)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(2)) == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b(uint256)", u256(0)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("b(uint256)", u256(1)), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("b(uint256)", u256(2)), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(functions_called_by_constructor) @@ -2485,8 +2501,8 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(2)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(access_base_storage) @@ -2510,9 +2526,9 @@ BOOST_AUTO_TEST_CASE(access_base_storage) } )"; 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)); + ABI_CHECK(callContractFunction("setData(uint256,uint256)", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("getViaBase()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("getViaDerived()"), encodeArgs(1, 2)); } BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) @@ -2528,9 +2544,9 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) contract Derived is Base, B, A { } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("setViaA(uint256)", 23) == encodeArgs()); - BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("getViaB()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("setViaA(uint256)", 23), encodeArgs()); + ABI_CHECK(callContractFunction("getViaB()"), encodeArgs(23)); } BOOST_AUTO_TEST_CASE(explicit_base_class) @@ -2544,8 +2560,8 @@ BOOST_AUTO_TEST_CASE(explicit_base_class) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(3)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(base_constructor_arguments) @@ -2567,7 +2583,7 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(7 * 7)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(7 * 7)); } BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) @@ -2587,7 +2603,7 @@ BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) @@ -2609,7 +2625,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(constructor_argument_overriding) @@ -2627,7 +2643,7 @@ BOOST_AUTO_TEST_CASE(constructor_argument_overriding) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(internal_constructor) @@ -2649,8 +2665,8 @@ BOOST_AUTO_TEST_CASE(function_modifier) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getOne()") == encodeArgs(0)); - BOOST_CHECK(callContractFunctionWithValue("getOne()", 1) == encodeArgs(1)); + ABI_CHECK(callContractFunction("getOne()"), encodeArgs(0)); + ABI_CHECK(callContractFunctionWithValue("getOne()", 1), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(function_modifier_local_variables) @@ -2663,8 +2679,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_local_variables) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(3)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(function_modifier_loop) @@ -2676,7 +2692,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_loop) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(10)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation) @@ -2688,8 +2704,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(2)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return) @@ -2703,8 +2719,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(2)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(function_modifier_overriding) @@ -2719,7 +2735,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context) @@ -2742,7 +2758,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0x4300)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0x4300)); } BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) @@ -2759,7 +2775,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(4 | 2)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(4 | 2)); } BOOST_AUTO_TEST_CASE(function_modifier_multiple_times) @@ -2772,8 +2788,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(2 + 5 + 3)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(2 + 5 + 3)); } BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) @@ -2786,8 +2802,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(2 + 5 + 3)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) @@ -2803,7 +2819,7 @@ BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(-7))); } BOOST_AUTO_TEST_CASE(super) @@ -2815,7 +2831,7 @@ BOOST_AUTO_TEST_CASE(super) contract D is B, C { function f() returns (uint r) { return super.f() | 8; } } )"; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 | 2 | 4 | 8)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); } BOOST_AUTO_TEST_CASE(super_in_constructor) @@ -2827,7 +2843,7 @@ BOOST_AUTO_TEST_CASE(super_in_constructor) contract D is B, C { uint data; function D() { data = super.f() | 8; } function f() returns (uint r) { return data; } } )"; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 | 2 | 4 | 8)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); } BOOST_AUTO_TEST_CASE(super_alone) @@ -2836,7 +2852,7 @@ BOOST_AUTO_TEST_CASE(super_alone) contract A { function f() { super; } } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -2849,9 +2865,9 @@ BOOST_AUTO_TEST_CASE(fallback_function) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0)); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(inherited_fallback_function) @@ -2865,9 +2881,9 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) contract B is A {} )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0)); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(default_fallback_throws) @@ -2880,7 +2896,7 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(event) @@ -2980,21 +2996,21 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) u160 const c_loggedAddress = m_contractAddress; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("deposit()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data.empty()); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()"))); - BOOST_CHECK(callContractFunction("deposit(address)", c_loggedAddress) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress)); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)"))); - BOOST_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress, 100)); @@ -3032,21 +3048,21 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited) u160 const c_loggedAddress = m_contractAddress; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("deposit()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data.empty()); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()"))); - BOOST_CHECK(callContractFunction("deposit(address)", c_loggedAddress) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress)); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)"))); - BOOST_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress, 100)); @@ -3230,7 +3246,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); + ABI_CHECK(callContractFunction("f(uint256,uint256)", 5, 9), encodeArgs(9, 8)); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter) @@ -3243,7 +3259,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); + ABI_CHECK(callContractFunction("f(uint256)", 9), encodeArgs(9)); } BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) @@ -3258,11 +3274,13 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(13))))); + ABI_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13), encodeArgs( + dev::keccak256( + toBigEndian(u256(10)) + + toBigEndian(u256(12)) + + toBigEndian(u256(13)) + ) + )); } BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_numeric_literals) @@ -3277,11 +3295,13 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_numeric_literals) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - bytes{0x0, 0xc} + - bytes(1, 0x91)))); + ABI_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12), encodeArgs( + dev::keccak256( + toBigEndian(u256(10)) + + bytes{0x0, 0xc} + + bytes(1, 0x91) + ) + )); } BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) @@ -3300,14 +3320,16 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo"))); + ABI_CHECK(callContractFunction("foo()"), encodeArgs(dev::keccak256("foo"))); - BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - bytes{0x0, 0xc} + - bytes(1, 0x91) + - bytes{0x66, 0x6f, 0x6f}))); + ABI_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12), encodeArgs( + dev::keccak256( + toBigEndian(u256(10)) + + bytes{0x0, 0xc} + + bytes(1, 0x91) + + bytes{0x66, 0x6f, 0x6f} + ) + )); } BOOST_AUTO_TEST_CASE(keccak256_with_bytes) @@ -3326,7 +3348,7 @@ BOOST_AUTO_TEST_CASE(keccak256_with_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("foo()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) @@ -3345,7 +3367,7 @@ BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs( + ABI_CHECK(callContractFunction("foo()"), encodeArgs( u256(dev::keccak256(bytes{'b'} + dev::keccak256("xyz").asBytes() + bytes{'a'})) )); } @@ -3361,7 +3383,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( + ABI_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13), encodeArgs( dev::keccak256( toBigEndian(u256(10)) + toBigEndian(u256(12)) + @@ -3416,10 +3438,10 @@ BOOST_AUTO_TEST_CASE(generic_callcode) u160 const c_receiverAddress = m_contractAddress; compileAndRun(sourceCode, 50, "Sender"); u160 const c_senderAddress = m_contractAddress; - BOOST_CHECK(callContractFunction("doSend(address)", c_receiverAddress) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("received()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("doSend(address)", c_receiverAddress), encodeArgs(0)); + ABI_CHECK(callContractFunction("received()"), encodeArgs(23)); m_contractAddress = c_receiverAddress; - BOOST_CHECK(callContractFunction("received()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("received()"), encodeArgs(0)); BOOST_CHECK(storageEmpty(c_receiverAddress)); BOOST_CHECK(!storageEmpty(c_senderAddress)); BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); @@ -3453,14 +3475,14 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) compileAndRun(sourceCode, 50, "Sender"); u160 const c_senderAddress = m_contractAddress; BOOST_CHECK(m_sender != c_senderAddress); // just for sanity - BOOST_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress) == encodeArgs()); - BOOST_CHECK(callContractFunction("received()") == encodeArgs(u256(23))); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender))); - BOOST_CHECK(callContractFunction("value()") == encodeArgs(u256(11))); + ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs()); + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11))); m_contractAddress = c_receiverAddress; - BOOST_CHECK(callContractFunction("received()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("value()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(c_receiverAddress)); BOOST_CHECK(!storageEmpty(c_senderAddress)); BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); @@ -3480,8 +3502,8 @@ BOOST_AUTO_TEST_CASE(library_call_in_homestead) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); } BOOST_AUTO_TEST_CASE(store_bytes) @@ -3499,8 +3521,8 @@ BOOST_AUTO_TEST_CASE(store_bytes) )"; compileAndRun(sourceCode); // empty copy loop - BOOST_CHECK(callContractFunction("save()") == encodeArgs(24)); - BOOST_CHECK(callContractFunction("save()", "abcdefg") == encodeArgs(24)); + ABI_CHECK(callContractFunction("save()"), encodeArgs(24)); + ABI_CHECK(callContractFunction("save()", "abcdefg"), encodeArgs(24)); } BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) @@ -3537,14 +3559,14 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes) } )"; compileAndRun(sourceCode, 0, "sender"); - BOOST_CHECK(callContractFunction("receive(uint256)", 7) == bytes()); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("forward()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("clear()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("forward()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0x80)); + ABI_CHECK(callContractFunction("receive(uint256)", 7), bytes()); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("clear()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80)); } BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) @@ -3570,14 +3592,14 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) } )"; compileAndRun(sourceCode, 0, "sender"); - BOOST_CHECK(callContractFunction("receive(uint256)", 7) == bytes()); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("forward(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("forward(bool)", false) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(16)); - BOOST_CHECK(callContractFunction("forward(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0x80)); + ABI_CHECK(callContractFunction("receive(uint256)", 7), bytes()); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("forward(bool)", false), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(16)); + ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80)); } BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) @@ -3590,9 +3612,9 @@ BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("---", 7) == bytes()); + ABI_CHECK(callContractFunction("---", 7), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("del()", 7) == encodeArgs(true)); + ABI_CHECK(callContractFunction("del()", 7), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3606,7 +3628,7 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); sendMessage(bytes(), false); BOOST_CHECK(m_output == bytes()); @@ -3624,9 +3646,9 @@ BOOST_AUTO_TEST_CASE(copy_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("reset()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("reset()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3641,16 +3663,16 @@ BOOST_AUTO_TEST_CASE(bytes_inside_mappings) )"; compileAndRun(sourceCode); // store a short byte array at 1 and a longer one at 2 - BOOST_CHECK(callContractFunction("set(uint256)", 1, 2) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256)", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); // copy shorter to longer - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); // copy empty to both - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3664,9 +3686,9 @@ BOOST_AUTO_TEST_CASE(bytes_length_member) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("set()", 1, 2) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(4+32+32)); + ABI_CHECK(callContractFunction("getLength()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("set()", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("getLength()"), encodeArgs(4+32+32)); } BOOST_AUTO_TEST_CASE(struct_copy) @@ -3697,16 +3719,16 @@ BOOST_AUTO_TEST_CASE(struct_copy) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set(uint256)", 7) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 0, 7) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(0, 0, 0, 0)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(0, 0, 0, 0)); + ABI_CHECK(callContractFunction("set(uint256)", 7), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 0, 7), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(0, 0, 0, 0)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(0, 0, 0, 0)); } BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) @@ -3735,13 +3757,13 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) compileAndRun(sourceCode); string data = "123456789012345678901234567890123"; BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("del()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("del()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3762,7 +3784,7 @@ BOOST_AUTO_TEST_CASE(struct_copy_via_local) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(using_enums) @@ -3782,7 +3804,7 @@ BOOST_AUTO_TEST_CASE(using_enums) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getChoice()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(enum_explicit_overflow) @@ -3813,12 +3835,12 @@ BOOST_AUTO_TEST_CASE(enum_explicit_overflow) )"; compileAndRun(sourceCode); // These should throw - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 3) == encodeArgs()); - BOOST_CHECK(callContractFunction("getChoiceFromSigned(int256)", -1) == encodeArgs()); - BOOST_CHECK(callContractFunction("getChoiceFromNegativeLiteral()") == encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 3), encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceFromSigned(int256)", -1), encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceFromNegativeLiteral()"), encodeArgs()); // These should work - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 2) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 0) == encodeArgs(0)); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 2), encodeArgs(2)); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 0), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(storing_invalid_boolean) @@ -3853,10 +3875,10 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("perm()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("ret()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("ev()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("set()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("perm()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("ret()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("ev()"), encodeArgs(1)); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(1)); @@ -3877,7 +3899,7 @@ BOOST_AUTO_TEST_CASE(using_contract_enums_with_explicit_contract_name) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(using_inherited_enum) @@ -3895,7 +3917,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(using_inherited_enum_excplicitly) @@ -3913,7 +3935,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum_excplicitly) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) @@ -3928,7 +3950,7 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(inline_member_init) @@ -3949,7 +3971,7 @@ BOOST_AUTO_TEST_CASE(inline_member_init) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(5, 6, 8)); + ABI_CHECK(callContractFunction("get()"), encodeArgs(5, 6, 8)); } BOOST_AUTO_TEST_CASE(inline_member_init_inheritence) @@ -3966,8 +3988,8 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence) function getDMember() returns (uint i) { return m_derived; } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getBMember()") == encodeArgs(5)); - BOOST_CHECK(callContractFunction("getDMember()") == encodeArgs(6)); + ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); + ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); } BOOST_AUTO_TEST_CASE(inline_member_init_inheritence_without_constructor) @@ -3982,8 +4004,8 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence_without_constructor) function getDMember() returns (uint i) { return m_derived; } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getBMember()") == encodeArgs(5)); - BOOST_CHECK(callContractFunction("getDMember()") == encodeArgs(6)); + ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); + ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); } BOOST_AUTO_TEST_CASE(external_function) @@ -3998,7 +4020,7 @@ BOOST_AUTO_TEST_CASE(external_function) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", 2, 3) == encodeArgs(2+7, 3)); + ABI_CHECK(callContractFunction("test(uint256,uint256)", 2, 3), encodeArgs(2+7, 3)); } BOOST_AUTO_TEST_CASE(bytes_in_arguments) @@ -4026,8 +4048,10 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) 12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, u256(innercalldata1.length()), innercalldata1, u256(innercalldata2.length()), innercalldata2); - BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) - == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); + ABI_CHECK( + callContractFunction("test(uint256,bytes,bytes,uint256)", calldata), + encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())) + ); } BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) @@ -4046,15 +4070,15 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); - BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); - BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); - BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); + ABI_CHECK(callContractFunction("setIDStatic(uint256)", 11), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 2), encodeArgs(11)); + ABI_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 7), encodeArgs(8)); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9), bytes()); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11), bytes()); + ABI_CHECK(callContractFunction("getData(uint256)", 7), encodeArgs(8, 9)); + ABI_CHECK(callContractFunction("getData(uint256)", 8), encodeArgs(10, 11)); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); } BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) @@ -4074,17 +4098,17 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(0, 0)); - BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); - BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); - BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); - BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); - BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(0, 0)); + ABI_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49), bytes()); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(48, 49)); + ABI_CHECK(callContractFunction("setIDStatic(uint256)", 11), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 2), encodeArgs(11)); + ABI_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 7), encodeArgs(8)); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9), bytes()); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11), bytes()); + ABI_CHECK(callContractFunction("getData(uint256)", 7), encodeArgs(8, 9)); + ABI_CHECK(callContractFunction("getData(uint256)", 8), encodeArgs(10, 11)); } BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) @@ -4098,14 +4122,14 @@ BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 5) == bytes()); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 400, 5) == bytes()); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("get(uint256)", 4) == bytes()); - BOOST_CHECK(callContractFunction("get(uint256)", 400) == bytes()); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 3, 4), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 4, 5), bytes()); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 400, 5), bytes()); + ABI_CHECK(callContractFunction("get(uint256)", 3), encodeArgs(4)); + ABI_CHECK(callContractFunction("get(uint256)", 4), bytes()); + ABI_CHECK(callContractFunction("get(uint256)", 400), bytes()); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) @@ -4120,15 +4144,15 @@ BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == bytes()); - BOOST_CHECK(callContractFunction("enlarge(uint256)", 4) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 8) == bytes()); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("get(uint256)", 3), bytes()); + ABI_CHECK(callContractFunction("enlarge(uint256)", 4), encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 3, 4), encodeArgs(true)); + ABI_CHECK(callContractFunction("get(uint256)", 3), encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 4, 8), bytes()); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(fixed_array_cleanup) @@ -4146,9 +4170,9 @@ BOOST_AUTO_TEST_CASE(fixed_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4167,9 +4191,9 @@ BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4189,11 +4213,11 @@ BOOST_AUTO_TEST_CASE(dynamic_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("halfClear()") == bytes()); + ABI_CHECK(callContractFunction("halfClear()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fullClear()") == bytes()); + ABI_CHECK(callContractFunction("fullClear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4215,9 +4239,9 @@ BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == encodeArgs(8)); + ABI_CHECK(callContractFunction("fill()"), encodeArgs(8)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4237,12 +4261,12 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4) == bytes()); - BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes()); - BOOST_CHECK(callContractFunction("getData2(uint256)", 5) == encodeArgs(10, 4)); - BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0) == bytes()); - BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes()); - BOOST_CHECK(callContractFunction("getData2(uint256)", 0) == encodeArgs(0, 0)); + ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4), bytes()); + ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes()); + ABI_CHECK(callContractFunction("getData2(uint256)", 5), encodeArgs(10, 4)); + ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0), bytes()); + ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes()); + ABI_CHECK(callContractFunction("getData2(uint256)", 0), encodeArgs(0, 0)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4264,7 +4288,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_static) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(8, 0)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(8, 0)); } BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic) @@ -4282,7 +4306,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(9, 4)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(9, 4)); } BOOST_AUTO_TEST_CASE(array_copy_different_packing) @@ -4305,7 +4329,7 @@ BOOST_AUTO_TEST_CASE(array_copy_different_packing) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000001")), asString(fromHex("0000000000000002")), asString(fromHex("0000000000000003")), @@ -4334,7 +4358,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000001")), asString(fromHex("0000000000000002")), asString(fromHex("0000000000000003")), @@ -4366,7 +4390,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( u256("0xffffffff"), asString(fromHex("0000000000000000""000000000a000900""0800070006000500""0400030002000100")), asString(fromHex("0000000000000000""0000000000000000""0000000000000000""0000000000000000")) @@ -4396,7 +4420,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000004")), asString(fromHex("0000000000000000")), asString(fromHex("0000000000000000")) @@ -4423,7 +4447,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(4, 5)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(4, 5)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4466,10 +4490,10 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) bytes valueSequence; for (size_t i = 0; i < 101; ++i) valueSequence += toBigEndian(u256(i)); - BOOST_CHECK(callContractFunction("test1()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test2()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test3()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test4()") == + ABI_CHECK(callContractFunction("test1()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test2()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test3()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test4()"), encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) + encodeArgs(101) + valueSequence + encodeArgs(101) + valueSequence + @@ -4501,7 +4525,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi_signed) )"; compileAndRun(sourceCode); bytes valueSequence; - BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x20, 8, + ABI_CHECK(callContractFunction("test()"), encodeArgs(0x20, 8, u256(-1), u256(-1), u256(8), @@ -4529,7 +4553,7 @@ BOOST_AUTO_TEST_CASE(array_push) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(5, 4, 3, 3)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(5, 4, 3, 3)); } BOOST_AUTO_TEST_CASE(byte_array_push) @@ -4549,7 +4573,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(external_array_args) @@ -4573,7 +4597,7 @@ BOOST_AUTO_TEST_CASE(external_array_args) 3, // b.length 11, 12, 13 // b ); - BOOST_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params) == encodeArgs(1, 12, 23)); + ABI_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params), encodeArgs(1, 12, 23)); } BOOST_AUTO_TEST_CASE(bytes_index_access) @@ -4607,9 +4631,9 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}; - BOOST_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); - BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); - BOOST_CHECK(callContractFunction("storageWrite()") == encodeArgs(0x193)); + ABI_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); + ABI_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); + ABI_CHECK(callContractFunction("storageWrite()"), encodeArgs(0x193)); } BOOST_AUTO_TEST_CASE(bytes_delete_element) @@ -4629,7 +4653,7 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test1()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test1()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) @@ -4657,7 +4681,7 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs( + ABI_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs( 21, 22, 23, 24, 25, 26, 27, 28, 29, // a u256(32 * (9 + 1)), 4, // size of b @@ -4665,8 +4689,8 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) 11, 12, 13, // b[1] 21, 22, 23, // b[2] 31, 32, 33 // b[3] - )) == encodeArgs(32)); - BOOST_CHECK(callContractFunction("retrieve()") == encodeArgs( + )), encodeArgs(32)); + ABI_CHECK(callContractFunction("retrieve()"), encodeArgs( 9, 28, 9, 28, 4, 3, 32)); } @@ -4687,12 +4711,12 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test(uint256[2][])", encodeArgs( + ABI_CHECK(callContractFunction("test(uint256[2][])", encodeArgs( 32, 3, 7, 8, 9, 10, 11, 12 - )) == encodeArgs(10)); + )), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(array_copy_including_mapping) @@ -4725,10 +4749,10 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x02000200)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000200)); // storage is not empty because we cannot delete the mappings BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == encodeArgs(7)); + ABI_CHECK(callContractFunction("clear()"), encodeArgs(7)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4754,14 +4778,14 @@ BOOST_AUTO_TEST_CASE(swap_in_storage_overwrite) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0), u256(0))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(0), u256(0))); - BOOST_CHECK(callContractFunction("set()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(3), u256(4))); - BOOST_CHECK(callContractFunction("swap()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("set()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(3), u256(4))); + ABI_CHECK(callContractFunction("swap()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(1), u256(2))); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) @@ -4781,7 +4805,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) @@ -4804,7 +4828,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) @@ -4824,7 +4848,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(simple_constant_variables_test) @@ -4835,7 +4859,7 @@ BOOST_AUTO_TEST_CASE(simple_constant_variables_test) uint constant x = 56; })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getX()") == encodeArgs(56)); + ABI_CHECK(callContractFunction("getX()"), encodeArgs(56)); } BOOST_AUTO_TEST_CASE(constant_variables) @@ -4859,7 +4883,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_expression) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0x123 + 0x456 + 1)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x123 + 0x456 + 1)); } BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) @@ -4871,7 +4895,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(dev::keccak256("abc"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(dev::keccak256("abc"))); } // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented @@ -4885,7 +4909,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // } // )"; // compileAndRun(sourceCode); -// BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 + 2 + 3)); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3)); //} // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented @@ -4899,7 +4923,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // } // )"; // compileAndRun(sourceCode); -// BOOST_CHECK(callContractFunction("f()") == encodeArgs(5)); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(5)); //} BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) @@ -4929,7 +4953,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_enum) @@ -4961,7 +4985,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_enum) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes) @@ -4991,7 +5015,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) @@ -5021,7 +5045,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -5035,7 +5059,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_first) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second) @@ -5048,7 +5072,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) @@ -5066,8 +5090,8 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(3)); - BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs(10)); + ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(3)); + ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) @@ -5080,7 +5104,7 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) @@ -5094,8 +5118,8 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(super_overload) @@ -5109,8 +5133,8 @@ BOOST_AUTO_TEST_CASE(super_overload) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(bool_conversion) @@ -5129,16 +5153,16 @@ BOOST_AUTO_TEST_CASE(bool_conversion) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bool)", 0) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("f(bool)", 1) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 2) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 3) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 255) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 0) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("g(bool)", 1) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 2) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 3) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 255) == encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 0), encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bool)", 1), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 2), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 3), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 255), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 0), encodeArgs(0)); + ABI_CHECK(callContractFunction("g(bool)", 1), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 2), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 3), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 255), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_signed) @@ -5179,8 +5203,8 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7))); - BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(9), u256(7))); + ABI_CHECK(callContractFunction("t2()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(invalid_enum_compared) @@ -5210,10 +5234,10 @@ BOOST_AUTO_TEST_CASE(invalid_enum_compared) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_eq_ok()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("test_eq_ok()"), encodeArgs(u256(1))); // both should throw - BOOST_CHECK(callContractFunction("test_eq()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_neq()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_eq()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_neq()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_logged) @@ -5239,7 +5263,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_log_ok()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("test_log_ok()"), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); @@ -5247,7 +5271,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0))); // should throw - BOOST_CHECK(callContractFunction("test_log()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_log()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_stored) @@ -5272,11 +5296,11 @@ BOOST_AUTO_TEST_CASE(invalid_enum_stored) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_store_ok()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("test_store_ok()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); // should throw - BOOST_CHECK(callContractFunction("test_store()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_store()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) @@ -5308,9 +5332,9 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) )"; compileAndRun(sourceCode, 0, "C"); // both should throw - BOOST_CHECK(callContractFunction("test_return()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_inline_assignment()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_assignment()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_return()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_inline_assignment()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_assignment()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg) @@ -5336,7 +5360,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg) )"; compileAndRun(sourceCode, 0, "C"); // should throw - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); } @@ -5361,12 +5385,12 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) } )"; compileAndRun(sourceCode, 0, "init_fix"); - BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("isOk()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("ok()"), encodeArgs(true)); compileAndRun(sourceCode, 0, "fix_init"); - BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("isOk()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("ok()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) @@ -5400,7 +5424,7 @@ BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("assign()") == encodeArgs(2, 2, 3, 3)); + ABI_CHECK(callContractFunction("assign()"), encodeArgs(2, 2, 3, 3)); } BOOST_AUTO_TEST_CASE(struct_delete_member) @@ -5426,7 +5450,7 @@ BOOST_AUTO_TEST_CASE(struct_delete_member) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("deleteMember()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("deleteMember()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) @@ -5451,7 +5475,7 @@ BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("deleteIt()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("deleteIt()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(evm_exceptions_out_of_band_access) @@ -5473,9 +5497,9 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_out_of_band_access) } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("testIt()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("testIt()"), encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_call_fail) @@ -5498,8 +5522,8 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_call_fail) )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("testIt()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("testIt()"), encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) @@ -5529,9 +5553,9 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(2)); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(127)); - BOOST_CHECK(callContractFunction("q()") == encodeArgs(250)); + ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("y()"), encodeArgs(127)); + ABI_CHECK(callContractFunction("q()"), encodeArgs(250)); } BOOST_AUTO_TEST_CASE(failing_send) @@ -5624,9 +5648,9 @@ BOOST_AUTO_TEST_CASE(return_string) string s("Julia"); bytes args = encodeArgs(u256(0x20), u256(s.length()), s); BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get1()") == args); - BOOST_CHECK(callContractFunction("get2()") == args); - BOOST_CHECK(callContractFunction("s()") == args); + ABI_CHECK(callContractFunction("get1()"), args); + ABI_CHECK(callContractFunction("get2()"), args); + ABI_CHECK(callContractFunction("s()"), args); } BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) @@ -5672,9 +5696,9 @@ BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) encodeArgs(u256(l1)) ); bytes result = encodeArgs(u256(0x40), u256(0x40 + dyn1.size())) + dyn1 + dyn2; - BOOST_CHECK(callContractFunction("get()") == result); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("get()"), result); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2); } } @@ -5740,16 +5764,16 @@ BOOST_AUTO_TEST_CASE(bytes_in_function_calls) callContractFunction("setIndirectFromMemory(string,uint256,string)", asString(args1)) == encodeArgs(u256(l1)) ); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2); // swapped bytes args2 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn2.size())) + dyn2 + dyn1; BOOST_REQUIRE( callContractFunction("setIndirectFromCalldata(string,uint256,string)", asString(args2)) == encodeArgs(u256(l1)) ); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn2); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn1); } } @@ -5946,10 +5970,10 @@ BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage) callContractFunction("set(uint24[])", u256(0x20), u256(data.size()), data) == encodeArgs(u256(data.size())) ); - BOOST_CHECK(callContractFunction("data(uint256)", u256(7)) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(15)) == encodeArgs(u256(16))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(18)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0x20), u256(data.size()), data)); + ABI_CHECK(callContractFunction("data(uint256)", u256(7)), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("data(uint256)", u256(15)), encodeArgs(u256(16))); + ABI_CHECK(callContractFunction("data(uint256)", u256(18)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size()), data)); } BOOST_AUTO_TEST_CASE(arrays_complex_from_and_to_storage) @@ -5973,10 +5997,10 @@ BOOST_AUTO_TEST_CASE(arrays_complex_from_and_to_storage) callContractFunction("set(uint24[3][])", u256(0x20), u256(data.size() / 3), data) == encodeArgs(u256(data.size() / 3)) ); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(2), u256(2)) == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(5), u256(1)) == encodeArgs(u256(17))); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(6), u256(0)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0x20), u256(data.size() / 3), data)); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(2), u256(2)), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(5), u256(1)), encodeArgs(u256(17))); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(6), u256(0)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size() / 3), data)); } BOOST_AUTO_TEST_CASE(arrays_complex_memory_index_access) @@ -6062,19 +6086,19 @@ BOOST_AUTO_TEST_CASE(storage_array_ref) BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(-1))); BOOST_REQUIRE(callContractFunction("add(uint256)", u256(7)) == encodeArgs()); BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("add(uint256)", u256(11)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(17)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(27)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(31)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(32)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(66)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(177)) == encodeArgs()); - BOOST_CHECK(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(27)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(32)) == encodeArgs(u256(5))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(176)) == encodeArgs(u256(-1))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(0)) == encodeArgs(u256(-1))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(400)) == encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("add(uint256)", u256(11)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(17)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(27)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(31)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(32)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(66)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(177)), encodeArgs()); + ABI_CHECK(callContractFunction("find(uint256)", u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("find(uint256)", u256(27)), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("find(uint256)", u256(32)), encodeArgs(u256(5))); + ABI_CHECK(callContractFunction("find(uint256)", u256(176)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("find(uint256)", u256(0)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("find(uint256)", u256(400)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(memory_types_initialisation) @@ -6093,10 +6117,10 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("stat()") == encodeArgs(vector(5))); - BOOST_CHECK(callContractFunction("dyn()") == encodeArgs(u256(0x20), u256(0))); - BOOST_CHECK(callContractFunction("nested()") == encodeArgs(u256(0x20), u256(0))); - BOOST_CHECK(callContractFunction("nestedStat()") == encodeArgs(vector(3 * 7))); + ABI_CHECK(callContractFunction("stat()"), encodeArgs(vector(5))); + ABI_CHECK(callContractFunction("dyn()"), encodeArgs(u256(0x20), u256(0))); + ABI_CHECK(callContractFunction("nested()"), encodeArgs(u256(0x20), u256(0))); + ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector(3 * 7))); } BOOST_AUTO_TEST_CASE(memory_arrays_delete) @@ -6125,7 +6149,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_delete) v = i * 0x10 + j; data[i * 3 + j] = v; } - BOOST_CHECK(callContractFunction("del()") == encodeArgs(data)); + ABI_CHECK(callContractFunction("del()"), encodeArgs(data)); } BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write) @@ -6148,7 +6172,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write) vector data(3 * 4); data[3 * 2 + 2] = 1; data[3 * 3 + 2] = 7; - BOOST_CHECK(callContractFunction("f()") == encodeArgs(data)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(data)); } BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) @@ -6172,7 +6196,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) vector data(3 * 4); data[3 * 2 + 2] = 1; data[3 * 3 + 2] = 7; - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x20), u256(4), data)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x20), u256(4), data)); } BOOST_AUTO_TEST_CASE(memory_structs_read_write) @@ -6215,9 +6239,9 @@ BOOST_AUTO_TEST_CASE(memory_structs_read_write) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("testInit()") == encodeArgs(u256(0), u256(0), u256(0), u256(0), true)); - BOOST_CHECK(callContractFunction("testCopyRead()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); - BOOST_CHECK(callContractFunction("testAssign()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("testInit()"), encodeArgs(u256(0), u256(0), u256(0), u256(0), true)); + ABI_CHECK(callContractFunction("testCopyRead()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("testAssign()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) @@ -6245,7 +6269,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(1), u256(2), u256(3))); } BOOST_AUTO_TEST_CASE(memory_structs_nested) @@ -6277,7 +6301,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(memory_structs_nested_load) @@ -6323,8 +6347,8 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested_load) compileAndRun(sourceCode, 0, "Test"); auto out = encodeArgs(u256(1), u256(2), u256(3), u256(4), u256(5), u256(6)); - BOOST_CHECK(callContractFunction("load()") == out); - BOOST_CHECK(callContractFunction("store()") == out); + ABI_CHECK(callContractFunction("load()"), out); + ABI_CHECK(callContractFunction("store()"), out); } BOOST_AUTO_TEST_CASE(struct_constructor_nested) @@ -6351,7 +6375,7 @@ BOOST_AUTO_TEST_CASE(struct_constructor_nested) compileAndRun(sourceCode, 0, "C"); auto out = encodeArgs(u256(1), u256(0), u256(9), u256(0), u256(4), u256(5)); - BOOST_CHECK(callContractFunction("get()") == out); + ABI_CHECK(callContractFunction("get()"), out); } BOOST_AUTO_TEST_CASE(struct_named_constructor) @@ -6367,7 +6391,7 @@ BOOST_AUTO_TEST_CASE(struct_named_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("s()") == encodeArgs(u256(1), true)); + ABI_CHECK(callContractFunction("s()"), encodeArgs(u256(1), true)); } BOOST_AUTO_TEST_CASE(literal_strings) @@ -6393,11 +6417,11 @@ BOOST_AUTO_TEST_CASE(literal_strings) string shortStr = "123"; string hello = "Hello, World!"; - BOOST_CHECK(callContractFunction("f()") == encodeDyn(hello)); - BOOST_CHECK(callContractFunction("long()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("medium()") == encodeDyn(medium)); - BOOST_CHECK(callContractFunction("short()") == encodeDyn(shortStr)); - BOOST_CHECK(callContractFunction("empty()") == encodeDyn(string())); + ABI_CHECK(callContractFunction("f()"), encodeDyn(hello)); + ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("medium()"), encodeDyn(medium)); + ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr)); + ABI_CHECK(callContractFunction("empty()"), encodeDyn(string())); } BOOST_AUTO_TEST_CASE(initialise_string_constant) @@ -6412,8 +6436,8 @@ BOOST_AUTO_TEST_CASE(initialise_string_constant) string longStr = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; string shortStr = "abcdef"; - BOOST_CHECK(callContractFunction("long()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("short()") == encodeDyn(shortStr)); + ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr)); } BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) @@ -6436,7 +6460,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -6454,14 +6478,14 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "f(string,uint256)", u256(0x40), u256(2), u256(6), string("abcdef") - ) == encodeArgs("c")); - BOOST_CHECK(callContractFunction("l()") == encodeArgs(u256(6))); + ), encodeArgs("c")); + ABI_CHECK(callContractFunction("l()"), encodeArgs(u256(6))); } BOOST_AUTO_TEST_CASE(string_as_mapping_key) @@ -6505,7 +6529,7 @@ BOOST_AUTO_TEST_CASE(accessor_for_state_variable) })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("ticketPrice()") == encodeArgs(u256(500))); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); } BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) @@ -6516,7 +6540,7 @@ BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("ticketPrice()") == encodeArgs(u256(555))); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); } BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) @@ -6531,7 +6555,7 @@ BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) } )"; compileAndRun(text); - BOOST_CHECK(callContractFunction("getStateVar()") == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("getStateVar()"), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture) @@ -6547,7 +6571,7 @@ BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inherited_function) { @@ -6562,7 +6586,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) { )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { @@ -6577,7 +6601,7 @@ BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(inherited_constant_state_var) @@ -6594,7 +6618,7 @@ BOOST_AUTO_TEST_CASE(inherited_constant_state_var) )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(multiple_inherited_state_vars) @@ -6625,12 +6649,12 @@ BOOST_AUTO_TEST_CASE(multiple_inherited_state_vars) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("b()") == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("a_set(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b_set(uint256)", u256(3)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("b()"), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("a_set(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b_set(uint256)", u256(3)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(constant_string_literal) @@ -6657,12 +6681,12 @@ BOOST_AUTO_TEST_CASE(constant_string_literal) compileAndRun(sourceCode); string longStr = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; string shortStr = "abcdefghijklmnopq"; - BOOST_CHECK(callContractFunction("b()") == encodeArgs(shortStr)); - BOOST_CHECK(callContractFunction("x()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("getB()") == encodeArgs(shortStr)); - BOOST_CHECK(callContractFunction("getX()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("getX2()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("unused()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("b()"), encodeArgs(shortStr)); + ABI_CHECK(callContractFunction("x()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("getB()"), encodeArgs(shortStr)); + ABI_CHECK(callContractFunction("getX()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("getX2()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("unused()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) @@ -6677,7 +6701,7 @@ BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(library_call) @@ -6692,7 +6716,7 @@ BOOST_AUTO_TEST_CASE(library_call) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(33) * 9)); + ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9)); } BOOST_AUTO_TEST_CASE(library_stray_values) @@ -6709,7 +6733,7 @@ BOOST_AUTO_TEST_CASE(library_stray_values) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(cross_contract_types) @@ -6724,7 +6748,7 @@ BOOST_AUTO_TEST_CASE(cross_contract_types) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(simple_throw) @@ -6741,8 +6765,8 @@ BOOST_AUTO_TEST_CASE(simple_throw) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(11)) == encodeArgs(u256(21))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(uint256)", u256(11)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(strings_in_struct) @@ -6781,10 +6805,10 @@ BOOST_AUTO_TEST_CASE(strings_in_struct) )"; compileAndRun(sourceCode); string s = "asdfghjkl"; - BOOST_CHECK(callContractFunction("getFirst()") == encodeArgs(u256(10))); - BOOST_CHECK(callContractFunction("getSecond()") == encodeArgs(u256(20))); - BOOST_CHECK(callContractFunction("getThird()") == encodeArgs(u256(30))); - BOOST_CHECK(callContractFunction("getLast()") == encodeDyn(s)); + ABI_CHECK(callContractFunction("getFirst()"), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("getSecond()"), encodeArgs(u256(20))); + ABI_CHECK(callContractFunction("getThird()"), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("getLast()"), encodeDyn(s)); } BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) @@ -6810,7 +6834,7 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) } )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs( + ABI_CHECK(callContractFunction("f()"), encodeArgs( u256(2), u256(3), u256(4), u256(5), u256(6), // first return argument u256(1000), u256(1001), u256(1002), u256(1003), u256(1004)) // second return argument ); @@ -6842,7 +6866,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17))); } BOOST_AUTO_TEST_CASE(using_library_structs) @@ -6869,7 +6893,7 @@ BOOST_AUTO_TEST_CASE(using_library_structs) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), u256(8))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), u256(8))); } BOOST_AUTO_TEST_CASE(library_struct_as_an_expression) @@ -6890,7 +6914,7 @@ BOOST_AUTO_TEST_CASE(library_struct_as_an_expression) } )"; compileAndRun(sourceCode, 0, "Tsra"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(library_enum_as_an_expression) @@ -6911,7 +6935,7 @@ BOOST_AUTO_TEST_CASE(library_enum_as_an_expression) } )"; compileAndRun(sourceCode, 0, "Tsra"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(short_strings) @@ -7015,12 +7039,12 @@ BOOST_AUTO_TEST_CASE(short_strings) } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("data1()") == encodeDyn(string("123"))); - BOOST_CHECK(callContractFunction("lengthChange()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("data1()"), encodeDyn(string("123"))); + ABI_CHECK(callContractFunction("lengthChange()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("deleteElements()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("deleteElements()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("copy()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -7040,7 +7064,7 @@ BOOST_AUTO_TEST_CASE(calldata_offset) } )"; compileAndRun(sourceCode, 0, "CB", encodeArgs(u256(0x20))); - BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd"))); + ABI_CHECK(callContractFunction("last()", encodeArgs()), encodeDyn(string("nd"))); } BOOST_AUTO_TEST_CASE(contract_binary_dependencies) @@ -7070,10 +7094,10 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library) compileAndRun(sourceCode, 10, "c"); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); - BOOST_CHECK(callContractFunction("f(address)", encodeArgs(u160(libraryAddress))) == encodeArgs(false)); + ABI_CHECK(callContractFunction("f(address)", encodeArgs(u160(libraryAddress))), encodeArgs(false)); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); - BOOST_CHECK(callContractFunction("f(address)", encodeArgs(u160(m_contractAddress))) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f(address)", encodeArgs(u160(m_contractAddress))), encodeArgs(true)); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); } @@ -7099,7 +7123,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", encodeArgs()) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()", encodeArgs()), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(tuples) @@ -7130,7 +7154,7 @@ BOOST_AUTO_TEST_CASE(tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(string_tuples) @@ -7149,8 +7173,8 @@ BOOST_AUTO_TEST_CASE(string_tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(8), u256(3), string("abc"))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("abc"), u256(3), string("def"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x40), u256(8), u256(3), string("abc"))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0x40), u256(0x80), u256(3), string("abc"), u256(3), string("def"))); } BOOST_AUTO_TEST_CASE(decayed_tuple) @@ -7165,7 +7189,7 @@ BOOST_AUTO_TEST_CASE(decayed_tuple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers) @@ -7179,7 +7203,7 @@ BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(destructuring_assignment) @@ -7218,7 +7242,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), string("abcde")) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), string("abcde")), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(destructuring_assignment_wildcard) @@ -7243,7 +7267,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment_wildcard) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(lone_struct_array_type) @@ -7258,7 +7282,7 @@ BOOST_AUTO_TEST_CASE(lone_struct_array_type) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(create_memory_array) @@ -7280,7 +7304,7 @@ BOOST_AUTO_TEST_CASE(create_memory_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(string("A"), u256(8), u256(4), string("B"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B"))); } BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) @@ -7301,8 +7325,8 @@ BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(3), u256(1))) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))) == encodeArgs(u256(70))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(3), u256(1))), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))), encodeArgs(u256(70))); } BOOST_AUTO_TEST_CASE(memory_overwrite) @@ -7317,7 +7341,7 @@ BOOST_AUTO_TEST_CASE(memory_overwrite) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("b23a5"))); + ABI_CHECK(callContractFunction("f()"), encodeDyn(string("b23a5"))); } BOOST_AUTO_TEST_CASE(addmod_mulmod) @@ -7336,7 +7360,7 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(divisiod_by_zero) @@ -7352,12 +7376,12 @@ BOOST_AUTO_TEST_CASE(divisiod_by_zero) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 2) == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("div(uint256,uint256)", 7, 2), encodeArgs(u256(3))); // throws - BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 0) == encodeArgs()); - BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("div(uint256,uint256)", 7, 0), encodeArgs()); + ABI_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2), encodeArgs(u256(1))); // throws - BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0) == encodeArgs()); + ABI_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0), encodeArgs()); } BOOST_AUTO_TEST_CASE(string_allocation_bug) @@ -7378,7 +7402,7 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("p(uint256)") == encodeArgs( + ABI_CHECK(callContractFunction("p(uint256)"), encodeArgs( u256(0xbbbb), u256(0xcccc), u256(0x80), @@ -7403,7 +7427,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(9)) == encodeArgs(u256(2 * 9))); + ABI_CHECK(callContractFunction("f(uint256)", u256(9)), encodeArgs(u256(2 * 9))); } BOOST_AUTO_TEST_CASE(using_for_function_on_struct) @@ -7421,8 +7445,8 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(3 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(3 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(3 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(3 * 7))); } BOOST_AUTO_TEST_CASE(using_for_overload) @@ -7444,8 +7468,8 @@ BOOST_AUTO_TEST_CASE(using_for_overload) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(using_for_by_name) @@ -7463,8 +7487,8 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -7483,8 +7507,8 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(bound_function_to_string) @@ -7506,8 +7530,8 @@ BOOST_AUTO_TEST_CASE(bound_function_to_string) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) @@ -7523,7 +7547,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); } BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) @@ -7537,10 +7561,10 @@ BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0x20), u256(4), string("This"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(0x20), u256(2), string("is"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0x20), u256(2), string("an"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(0x20), u256(5), string("array"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(0x20), u256(4), string("This"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(0x20), u256(2), string("is"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(0x20), u256(2), string("an"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(0x20), u256(5), string("array"))); } BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) @@ -7556,7 +7580,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(3, 6)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3, 6)); } BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) @@ -7569,7 +7593,7 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) @@ -7586,8 +7610,8 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); - BOOST_CHECK(callContractFunction("tester()") == encodeArgs(u256(0x20), u256(3), string("abc"))); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); + ABI_CHECK(callContractFunction("tester()"), encodeArgs(u256(0x20), u256(3), string("abc"))); } BOOST_AUTO_TEST_CASE(inline_array_return) @@ -7606,7 +7630,7 @@ BOOST_AUTO_TEST_CASE(inline_array_return) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1, 2, 3, 4, 5)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1, 2, 3, 4, 5)); } BOOST_AUTO_TEST_CASE(inline_array_singleton) @@ -7620,7 +7644,7 @@ BOOST_AUTO_TEST_CASE(inline_array_singleton) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(inline_long_string_return) @@ -7635,7 +7659,7 @@ BOOST_AUTO_TEST_CASE(inline_long_string_return) string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(strLong)); + ABI_CHECK(callContractFunction("f()"), encodeDyn(strLong)); } BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) @@ -7654,9 +7678,9 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bytes32)", "789") == encodeArgs("9")); - BOOST_CHECK(callContractFunction("g(bytes32)", "789") == encodeArgs(u256(int('5')))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(1)) == encodeArgs("8")); + ABI_CHECK(callContractFunction("f(bytes32)", "789"), encodeArgs("9")); + ABI_CHECK(callContractFunction("g(bytes32)", "789"), encodeArgs(u256(int('5')))); + ABI_CHECK(callContractFunction("data(uint256)", u256(1)), encodeArgs("8")); } BOOST_AUTO_TEST_CASE(fixed_bytes_length_access) @@ -7670,7 +7694,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_length_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bytes32)", "789") == encodeArgs(u256(32), u256(16), u256(8))); + ABI_CHECK(callContractFunction("f(bytes32)", "789"), encodeArgs(u256(32), u256(16), u256(8))); } BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack) @@ -7683,7 +7707,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), string("abcdef"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), string("abcdef"))); } BOOST_AUTO_TEST_CASE(inline_assembly_read_and_write_stack) @@ -7697,7 +7721,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_read_and_write_stack) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(45))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(45))); } BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) @@ -7714,7 +7738,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0x20), u256(5), string("12345"))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0x20), u256(5), string("12345"))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access) @@ -7739,8 +7763,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("z()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("z()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_inside_function) @@ -7766,8 +7790,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_inside_function) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("z()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("z()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) @@ -7791,10 +7815,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("separator()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("separator2()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("separator()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("separator2()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(inline_assembly_jumps) @@ -7819,8 +7843,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_jumps) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()", u256(5)) == encodeArgs(u256(13))); - BOOST_CHECK(callContractFunction("f()", u256(7)) == encodeArgs(u256(34))); + ABI_CHECK(callContractFunction("f()", u256(5)), encodeArgs(u256(13))); + ABI_CHECK(callContractFunction("f()", u256(7)), encodeArgs(u256(34))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_access) @@ -7839,8 +7863,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(5)) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("f(uint256)", u256(5)), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(10))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call) @@ -7864,7 +7888,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) @@ -7915,7 +7939,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7), u256(0x10))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7), u256(0x10))); } BOOST_AUTO_TEST_CASE(inline_assembly_embedded_function_call) @@ -7942,7 +7966,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_embedded_function_call) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(4), u256(7), u256(0x10))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(4), u256(7), u256(0x10))); } BOOST_AUTO_TEST_CASE(inline_assembly_switch) @@ -7960,10 +7984,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_switch) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inline_assembly_recursion) @@ -7984,11 +8008,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_recursion) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("f(uint256)", u256(4)), encodeArgs(u256(24))); } BOOST_AUTO_TEST_CASE(inline_assembly_for) @@ -8009,11 +8033,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("f(uint256)", u256(4)), encodeArgs(u256(24))); } BOOST_AUTO_TEST_CASE(inline_assembly_for2) @@ -8035,9 +8059,9 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for2) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0), u256(2), u256(0))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1), u256(4), u256(3))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0), u256(2), u256(0))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(0), u256(2), u256(0))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1), u256(4), u256(3))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(0), u256(2), u256(0))); } BOOST_AUTO_TEST_CASE(index_access_with_type_conversion) @@ -8075,7 +8099,7 @@ BOOST_AUTO_TEST_CASE(delete_on_array_of_structs) compileAndRun(sourceCode, 0, "C"); // This code interprets x as an array length and thus will go out of gas. // neither of the two should throw due to out-of-bounds access - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } @@ -8100,7 +8124,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_calling_private) @@ -8128,7 +8152,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_calling_private) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_bound) @@ -8153,7 +8177,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_bound) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) @@ -8178,7 +8202,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(iszero_bnot_correct) @@ -8198,7 +8222,7 @@ BOOST_AUTO_TEST_CASE(iszero_bnot_correct) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(cleanup_bytes_types) @@ -8216,7 +8240,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) )"; compileAndRun(sourceCode, 0, "C"); // We input longer data on purpose. - BOOST_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)) == encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(skip_dynamic_types) @@ -8235,7 +8259,7 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(7), u256(8))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(7), u256(8))); } BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) @@ -8261,7 +8285,7 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2), u256(6))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(2), u256(6))); } BOOST_AUTO_TEST_CASE(failed_create) @@ -8285,11 +8309,11 @@ BOOST_AUTO_TEST_CASE(failed_create) )"; compileAndRun(sourceCode, 20, "C"); BOOST_CHECK(callContractFunction("f(uint256)", 20) != encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", 20) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("stack(uint256)", 1023) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", 20), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("stack(uint256)", 1023), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) @@ -8303,7 +8327,7 @@ BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) @@ -8321,9 +8345,9 @@ BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(break_in_modifier) @@ -8343,9 +8367,9 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) @@ -8365,9 +8389,9 @@ BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(mutex) @@ -8429,11 +8453,11 @@ BOOST_AUTO_TEST_CASE(mutex) auto fund = m_contractAddress; BOOST_CHECK_EQUAL(balanceAt(fund), 500); compileAndRun(sourceCode, 0, "Attacker", encodeArgs(u160(fund))); - BOOST_CHECK(callContractFunction("setProtected(bool)", true) == encodeArgs()); - BOOST_CHECK(callContractFunction("attack()") == encodeArgs()); + ABI_CHECK(callContractFunction("setProtected(bool)", true), encodeArgs()); + ABI_CHECK(callContractFunction("attack()"), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(fund), 500); - BOOST_CHECK(callContractFunction("setProtected(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("attack()") == encodeArgs(u256(460))); + ABI_CHECK(callContractFunction("setProtected(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("attack()"), encodeArgs(u256(460))); BOOST_CHECK_EQUAL(balanceAt(fund), 460); } @@ -8450,7 +8474,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) @@ -8476,7 +8500,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) @@ -8497,7 +8521,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) @@ -8521,9 +8545,9 @@ BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(payable_constructor) @@ -8550,11 +8574,11 @@ BOOST_AUTO_TEST_CASE(payable_function) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(27))); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(27))); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27); - BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(28))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(28))); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); } @@ -8572,7 +8596,7 @@ BOOST_AUTO_TEST_CASE(payable_function_calls_library) )"; compileAndRun(sourceCode, 0, "L"); compileAndRun(sourceCode, 0, "C", bytes(), map{{"L", m_contractAddress}}); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7))); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(non_payable_throw) @@ -8589,14 +8613,14 @@ BOOST_AUTO_TEST_CASE(non_payable_throw) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs()); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunctionWithValue("a()", 27) == encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunctionWithValue("a()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); } @@ -8613,7 +8637,7 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); } @@ -8635,7 +8659,7 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) compileAndRun(sourceCode, 0, "C"); u160 cAddr = m_contractAddress; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f(address)", cAddr), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function) @@ -8657,8 +8681,8 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function) compileAndRun(sourceCode, 0, "C"); // This should throw exceptions - BOOST_CHECK(callContractFunction("intern()") == encodeArgs()); - BOOST_CHECK(callContractFunction("extern()") == encodeArgs()); + ABI_CHECK(callContractFunction("intern()"), encodeArgs()); + ABI_CHECK(callContractFunction("extern()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) @@ -8679,7 +8703,7 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs()); + ABI_CHECK(callContractFunction("t()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(pass_function_types_internally) @@ -8697,7 +8721,7 @@ BOOST_AUTO_TEST_CASE(pass_function_types_internally) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", 7), encodeArgs(u256(8))); } BOOST_AUTO_TEST_CASE(pass_function_types_externally) @@ -8718,8 +8742,8 @@ BOOST_AUTO_TEST_CASE(pass_function_types_externally) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", 7), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f2(uint256)", 7), encodeArgs(u256(8))); } BOOST_AUTO_TEST_CASE(receive_external_function_type) @@ -8734,10 +8758,10 @@ BOOST_AUTO_TEST_CASE(receive_external_function_type) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "f(function)", m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) - ) == encodeArgs(u256(7))); + ), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(return_external_function_type) @@ -8782,7 +8806,7 @@ BOOST_AUTO_TEST_CASE(store_function) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(store_function_in_constructor) @@ -8805,8 +8829,8 @@ BOOST_AUTO_TEST_CASE(store_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("result_in_constructor()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("result_in_constructor()"), encodeArgs(u256(4))); } // TODO: store bound internal library functions @@ -8829,7 +8853,7 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor) @@ -8848,7 +8872,7 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime) @@ -8869,8 +8893,8 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("initial()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("initial()"), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check) @@ -8891,7 +8915,7 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(function_type_library_internal) @@ -8916,7 +8940,7 @@ BOOST_AUTO_TEST_CASE(function_type_library_internal) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)) == encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)), encodeArgs(u256(11))); } @@ -8946,7 +8970,7 @@ BOOST_AUTO_TEST_CASE(call_function_returning_function) )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(mapping_of_functions) @@ -8981,12 +9005,12 @@ BOOST_AUTO_TEST_CASE(mapping_of_functions) )"; compileAndRun(sourceCode, 0, "Flow"); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("success()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("success()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("success()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_functions) @@ -9029,12 +9053,12 @@ BOOST_AUTO_TEST_CASE(packed_functions) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("set()") == encodeArgs()); - BOOST_CHECK(callContractFunction("t1()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("t3()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("t4()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("set()"), encodeArgs()); + ABI_CHECK(callContractFunction("t1()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t2()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("t3()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t4()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(function_memory_array) @@ -9060,12 +9084,12 @@ BOOST_AUTO_TEST_CASE(function_memory_array) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)) == encodeArgs(u256(11))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)) == encodeArgs(u256(12))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)) == encodeArgs(u256(13))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)) == encodeArgs(u256(15))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)) == encodeArgs(u256(18))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)) == encodeArgs()); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)), encodeArgs(u256(13))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)), encodeArgs(u256(15))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)), encodeArgs(u256(18))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)), encodeArgs()); } BOOST_AUTO_TEST_CASE(function_delete_storage) @@ -9089,10 +9113,10 @@ BOOST_AUTO_TEST_CASE(function_delete_storage) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("set()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("ca()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("d()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("ca()") == encodeArgs()); + ABI_CHECK(callContractFunction("set()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("ca()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("d()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("ca()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(function_delete_stack) @@ -9109,7 +9133,7 @@ BOOST_AUTO_TEST_CASE(function_delete_stack) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(copy_function_storage_array) @@ -9131,7 +9155,7 @@ BOOST_AUTO_TEST_CASE(copy_function_storage_array) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(function_array_cross_calls) @@ -9170,7 +9194,7 @@ BOOST_AUTO_TEST_CASE(function_array_cross_calls) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(5), u256(6), u256(7))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(5), u256(6), u256(7))); } BOOST_AUTO_TEST_CASE(external_function_to_address) @@ -9187,8 +9211,8 @@ BOOST_AUTO_TEST_CASE(external_function_to_address) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("g(function)", fromHex("00000000000000000000000000000000000004226121ff00000000000000000")) == encodeArgs(u160(0x42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g(function)", fromHex("00000000000000000000000000000000000004226121ff00000000000000000")), encodeArgs(u160(0x42))); } @@ -9215,8 +9239,8 @@ BOOST_AUTO_TEST_CASE(copy_internal_function_array_to_storage) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("one()") == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("two()") == encodeArgs()); + ABI_CHECK(callContractFunction("one()"), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("two()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_constant_left) @@ -9227,7 +9251,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x4200))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0x4200))); } BOOST_AUTO_TEST_CASE(shift_negative_constant_left) @@ -9238,7 +9262,7 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x4200))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(-0x4200))); } BOOST_AUTO_TEST_CASE(shift_constant_right) @@ -9249,7 +9273,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0x42))); } BOOST_AUTO_TEST_CASE(shift_negative_constant_right) @@ -9260,7 +9284,7 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(-0x42))); } BOOST_AUTO_TEST_CASE(shift_left) @@ -9273,12 +9297,12 @@ BOOST_AUTO_TEST_CASE(shift_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_uint32) @@ -9291,11 +9315,11 @@ BOOST_AUTO_TEST_CASE(shift_left_uint32) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_uint8) @@ -9308,8 +9332,8 @@ BOOST_AUTO_TEST_CASE(shift_left_uint8) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)), encodeArgs(u256(0x66))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_larger_type) @@ -9325,7 +9349,7 @@ BOOST_AUTO_TEST_CASE(shift_left_larger_type) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_assignment) @@ -9339,12 +9363,12 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) @@ -9358,11 +9382,11 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); } BOOST_AUTO_TEST_CASE(shift_right) @@ -9375,10 +9399,10 @@ BOOST_AUTO_TEST_CASE(shift_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_right_garbled) @@ -9395,8 +9419,8 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(0xf))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(0xf))); } BOOST_AUTO_TEST_CASE(shift_right_uint32) @@ -9409,10 +9433,10 @@ BOOST_AUTO_TEST_CASE(shift_right_uint32) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_right_uint8) @@ -9425,8 +9449,8 @@ BOOST_AUTO_TEST_CASE(shift_right_uint8) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)), encodeArgs(u256(0x66))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_right_assignment) @@ -9440,10 +9464,10 @@ BOOST_AUTO_TEST_CASE(shift_right_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) @@ -9456,10 +9480,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) @@ -9473,10 +9497,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue) @@ -9492,8 +9516,8 @@ BOOST_AUTO_TEST_CASE(shift_negative_rvalue) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)), encodeArgs()); + ABI_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) @@ -9511,8 +9535,8 @@ BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)), encodeArgs()); + ABI_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) @@ -9526,7 +9550,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x4200))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x4200))); } BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) @@ -9540,7 +9564,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x42))); } BOOST_AUTO_TEST_CASE(shift_cleanup) @@ -9556,7 +9580,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) @@ -9572,7 +9596,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_overflow) @@ -9588,13 +9612,13 @@ BOOST_AUTO_TEST_CASE(shift_overflow) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254))); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1), encodeArgs(u256(254))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0), encodeArgs(u256(255))); // Result is -128 and output is sign-extended, not zero-padded. - BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(0) - 128)); - BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); + ABI_CHECK(callContractFunction("leftS(int8,int8)", 1, 7), encodeArgs(u256(0) - 128)); + ABI_CHECK(callContractFunction("leftS(int8,int8)", 1, 6), encodeArgs(u256(64))); } BOOST_AUTO_TEST_CASE(shift_bytes) @@ -9610,8 +9634,8 @@ BOOST_AUTO_TEST_CASE(shift_bytes) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); - BOOST_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); + ABI_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs("901234567890" + string(8, 0))); + ABI_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs(string(8, 0) + "123456789012")); } BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) @@ -9631,8 +9655,8 @@ BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("left(uint8)", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); - BOOST_CHECK(callContractFunction("right(uint8)", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); + ABI_CHECK(callContractFunction("left(uint8)", 8 * 8), encodeArgs("901234567890" + string(8, 0))); + ABI_CHECK(callContractFunction("right(uint8)", 8 * 8), encodeArgs(string(8, 0) + "123456789012")); } BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) @@ -9650,7 +9674,7 @@ BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0xff), u256(0xff))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0xff), u256(0xff))); } BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) @@ -9672,7 +9696,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_storage_overflow) @@ -9692,7 +9716,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_overflow) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe))); } BOOST_AUTO_TEST_CASE(contracts_separated_with_comment) @@ -9756,7 +9780,7 @@ BOOST_AUTO_TEST_CASE(recursive_structs) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(invalid_instruction) @@ -9771,7 +9795,7 @@ BOOST_AUTO_TEST_CASE(invalid_instruction) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(assert_require) @@ -9792,11 +9816,11 @@ BOOST_AUTO_TEST_CASE(assert_require) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("h(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("h(bool)", true) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("h(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("h(bool)", true), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(revert) @@ -9817,10 +9841,10 @@ BOOST_AUTO_TEST_CASE(revert) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(negative_stack_height) @@ -9860,11 +9884,11 @@ BOOST_AUTO_TEST_CASE(literal_empty_string) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(scientific_notation) @@ -9892,12 +9916,12 @@ BOOST_AUTO_TEST_CASE(scientific_notation) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(20000000000))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(25))); - BOOST_CHECK(callContractFunction("i()") == encodeArgs(u256(-20000000000))); - BOOST_CHECK(callContractFunction("j()") == encodeArgs(u256(-2))); - BOOST_CHECK(callContractFunction("k()") == encodeArgs(u256(-25))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(20000000000))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(25))); + ABI_CHECK(callContractFunction("i()"), encodeArgs(u256(-20000000000))); + ABI_CHECK(callContractFunction("j()"), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("k()"), encodeArgs(u256(-25))); } BOOST_AUTO_TEST_CASE(interface_contract) @@ -9932,7 +9956,7 @@ BOOST_AUTO_TEST_CASE(interface_contract) compileAndRun(sourceCode, 0, "A"); u160 const recipient = m_contractAddress; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(address)", recipient) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f(address)", recipient), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(keccak256_assembly) @@ -9968,10 +9992,10 @@ BOOST_AUTO_TEST_CASE(keccak256_assembly) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("g()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("h()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("i()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + ABI_CHECK(callContractFunction("g()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + ABI_CHECK(callContractFunction("h()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + ABI_CHECK(callContractFunction("i()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); } BOOST_AUTO_TEST_CASE(multi_modifiers) @@ -9995,10 +10019,10 @@ BOOST_AUTO_TEST_CASE(multi_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f1()") == bytes()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f2()") == bytes()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("f1()"), bytes()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f2()"), bytes()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(12))); } BOOST_AUTO_TEST_CASE(inlineasm_empty_let) @@ -10016,7 +10040,7 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(0))); } BOOST_AUTO_TEST_CASE(bare_call_invalid_address) @@ -10036,9 +10060,9 @@ BOOST_AUTO_TEST_CASE(bare_call_invalid_address) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(delegatecall_return_value) @@ -10064,17 +10088,17 @@ BOOST_AUTO_TEST_CASE(delegatecall_return_value) } )DELIMITER"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("set(uint256)", u256(1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("set(uint256)", u256(42)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(function_types_sig) diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index a8e58c25789f..342d0875eae2 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -24,7 +24,7 @@ #include -#include "../ExecutionFramework.h" +#include #include #include From 3e5d81578a10cfa1afc50c12074c67572499b4fb Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 19 Sep 2017 19:02:13 +0100 Subject: [PATCH 009/108] Avoid switch fallthrough in CompilerUtils --- libsolidity/codegen/CompilerUtils.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 37aa1aea685e..4d273b876770 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -810,9 +810,8 @@ void CompilerUtils::convertType( if (_cleanupNeeded) m_context << Instruction::ISZERO << Instruction::ISZERO; break; - case Type::Category::Function: - { - if (targetTypeCategory == Type::Category::Integer) + default: + if (stackTypeCategory == Type::Category::Function && targetTypeCategory == Type::Category::Integer) { IntegerType const& targetType = dynamic_cast(_targetType); solAssert(targetType.isAddress(), "Function type can only be converted to address."); @@ -823,9 +822,7 @@ void CompilerUtils::convertType( m_context << Instruction::POP; break; } - } - // fall-through - default: + // All other types should not be convertible to non-equal types. solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) From 74972f5fa6c0e59a5178e17ebdb48453528c7169 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 19 Sep 2017 19:02:16 +0100 Subject: [PATCH 010/108] Avoid switch fallthrough in ExpressionCompiler --- libsolidity/codegen/ExpressionCompiler.cpp | 58 ++++++++++++---------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c94baa1078fc..63d7f1e6f22e 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1014,41 +1014,46 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) switch (_memberAccess.expression().annotation().type->category()) { case Type::Category::Contract: + case Type::Category::Integer: { bool alsoSearchInteger = false; - ContractType const& type = dynamic_cast(*_memberAccess.expression().annotation().type); - if (type.isSuper()) + if (_memberAccess.expression().annotation().type->category() == Type::Category::Contract) { - solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); - utils().pushCombinedFunctionEntryLabel(m_context.superFunction( - dynamic_cast(*_memberAccess.annotation().referencedDeclaration), - type.contractDefinition() - )); - } - else - { - // ordinary contract type - if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) + ContractType const& type = dynamic_cast(*_memberAccess.expression().annotation().type); + if (type.isSuper()) { - u256 identifier; - if (auto const* variable = dynamic_cast(declaration)) - identifier = FunctionType(*variable).externalIdentifier(); - else if (auto const* function = dynamic_cast(declaration)) - identifier = FunctionType(*function).externalIdentifier(); - else - solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, IntegerType(0, IntegerType::Modifier::Address), true); - m_context << identifier; + solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); + utils().pushCombinedFunctionEntryLabel(m_context.superFunction( + dynamic_cast(*_memberAccess.annotation().referencedDeclaration), + type.contractDefinition() + )); } else - // not found in contract, search in members inherited from address - alsoSearchInteger = true; + { + // ordinary contract type + if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) + { + u256 identifier; + if (auto const* variable = dynamic_cast(declaration)) + identifier = FunctionType(*variable).externalIdentifier(); + else if (auto const* function = dynamic_cast(declaration)) + identifier = FunctionType(*function).externalIdentifier(); + else + solAssert(false, "Contract member is neither variable nor function."); + utils().convertType(type, IntegerType(0, IntegerType::Modifier::Address), true); + m_context << identifier; + } + else + // not found in contract, search in members inherited from address + alsoSearchInteger = true; + } } + else + alsoSearchInteger = true; + if (!alsoSearchInteger) break; - } - // fall-through - case Type::Category::Integer: + if (member == "balance") { utils().convertType( @@ -1067,6 +1072,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else solAssert(false, "Invalid member access to integer"); break; + } case Type::Category::Function: if (member == "selector") { From cb6cdfe7801a3362a489d0fd39cc0ce5a7075fea Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 25 Sep 2017 09:41:04 +0100 Subject: [PATCH 011/108] Simplify switch statements by refactoring internal break statements --- libsolidity/codegen/CompilerUtils.cpp | 12 ++++---- libsolidity/codegen/ExpressionCompiler.cpp | 36 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 4d273b876770..c1171c1d2b1c 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -596,7 +596,6 @@ void CompilerUtils::convertType( storeInMemoryDynamic(IntegerType(256)); // stack: mempos datapos storeStringData(data); - break; } else solAssert( @@ -820,15 +819,16 @@ void CompilerUtils::convertType( // stack:
m_context << Instruction::POP; - break; } - - // All other types should not be convertible to non-equal types. - solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); - if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) + else + { + // All other types should not be convertible to non-equal types. + solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) m_context << ((u256(1) << (8 * _targetType.storageBytes())) - 1) << Instruction::AND; + } break; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 63d7f1e6f22e..b286594ab932 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1051,26 +1051,26 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else alsoSearchInteger = true; - if (!alsoSearchInteger) - break; - - if (member == "balance") + if (alsoSearchInteger) { - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), - true - ); - m_context << Instruction::BALANCE; + if (member == "balance") + { + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(0, IntegerType::Modifier::Address), + true + ); + m_context << Instruction::BALANCE; + } + else if ((set{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(0, IntegerType::Modifier::Address), + true + ); + else + solAssert(false, "Invalid member access to integer"); } - else if ((set{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), - true - ); - else - solAssert(false, "Invalid member access to integer"); break; } case Type::Category::Function: From d45629d909b8809273c5dcd09fb9ff81299d81d0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 25 Sep 2017 12:01:09 +0200 Subject: [PATCH 012/108] Update frequently-asked-questions.rst --- docs/frequently-asked-questions.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 387f16fe8f13..93dcfbb815a0 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -304,8 +304,9 @@ There are defaults for the storage location depending on which type of variable it concerns: * state variables are always in storage -* function arguments are always in memory -* local variables are always in the stack but reference storage +* function arguments are in memory by default +* local variables of struct, array or mapping type reference storage by default +* local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack Example:: From 95ec2fd0b647fc60c92e36212cec813475e79635 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 25 Sep 2017 19:25:00 +0200 Subject: [PATCH 013/108] Fix encoded EndToEnd inputs. --- test/libsolidity/SolidityEndToEndTest.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 82dedf853a43..0536626fafda 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1457,7 +1457,7 @@ BOOST_AUTO_TEST_CASE(msg_sig) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) @@ -1473,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(now) @@ -3090,7 +3090,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address indexed _from, bytes32 indexed _id, uint indexed _value, uint indexed _value2, bytes32 data) anonymous; - function deposit(bytes32 _id, bool _manually) payable { + function deposit(bytes32 _id) payable { Deposit(msg.sender, _id, msg.value, 2, "abc"); } } @@ -3098,7 +3098,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) compileAndRun(sourceCode); u256 value(18); u256 id(0x1234); - callContractFunctionWithValue("deposit(bytes32,bool)", value, id); + callContractFunctionWithValue("deposit(bytes32)", value, id); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs("abc")); @@ -3757,11 +3757,11 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) compileAndRun(sourceCode); string data = "123456789012345678901234567890123"; BOOST_CHECK(storageEmpty(m_contractAddress)); - ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); ABI_CHECK(callContractFunction("copy()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); - ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); ABI_CHECK(callContractFunction("del()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); @@ -7402,7 +7402,7 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("p(uint256)"), encodeArgs( + ABI_CHECK(callContractFunction("p(uint256)", 0), encodeArgs( u256(0xbbbb), u256(0xcccc), u256(0x80), From 5722f3083cae829c28a28083fa806005ed71168c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 21 Sep 2017 12:41:06 +0200 Subject: [PATCH 014/108] CMake: Add compiler warning about implicit fallthough --- cmake/EthCheckCXXCompilerFlag.cmake | 23 +++++++++++++++++++++++ cmake/EthCompilerSettings.cmake | 23 +++++++---------------- 2 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 cmake/EthCheckCXXCompilerFlag.cmake diff --git a/cmake/EthCheckCXXCompilerFlag.cmake b/cmake/EthCheckCXXCompilerFlag.cmake new file mode 100644 index 000000000000..c6ed35b4e230 --- /dev/null +++ b/cmake/EthCheckCXXCompilerFlag.cmake @@ -0,0 +1,23 @@ +include(CheckCXXCompilerFlag) + +# Adds CXX compiler flag if the flag is supported by the compiler. +# +# This is effectively a combination of CMake's check_cxx_compiler_flag() +# and add_compile_options(): +# +# if(check_cxx_compiler_flag(flag)) +# add_compile_options(flag) +# +function(eth_add_cxx_compiler_flag_if_supported FLAG) + # Remove leading - or / from the flag name. + string(REGEX REPLACE "^-|/" "" name ${FLAG}) + check_cxx_compiler_flag(${FLAG} ${name}) + if(${name}) + add_compile_options(${FLAG}) + endif() + + # If the optional argument passed, store the result there. + if(ARGV1) + set(${ARGV1} ${name} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 1a00ae7064e2..6d4dadeb2cfd 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -4,7 +4,7 @@ # CMake file for cpp-ethereum project which specifies our compiler settings # for each supported platform and build configuration. # -# See http://www.ethdocs.org/en/latest/ethereum-clients/cpp-ethereum/. +# The documentation for cpp-ethereum is hosted at http://cpp-ethereum.org # # Copyright (c) 2014-2016 cpp-ethereum contributors. #------------------------------------------------------------------------------ @@ -14,18 +14,15 @@ # # These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc) -include(CheckCXXCompilerFlag) +include(EthCheckCXXCompilerFlag) -check_cxx_compiler_flag(-fstack-protector-strong have_stack_protector_strong) -if (have_stack_protector_strong) - add_compile_options(-fstack-protector-strong) -else() - check_cxx_compiler_flag(-fstack-protector have_stack_protector) - if(have_stack_protector) - add_compile_options(-fstack-protector) - endif() +eth_add_cxx_compiler_flag_if_supported(-fstack-protector-strong have_stack_protector_strong_support) +if(NOT have_stack_protector_strong_support) + eth_add_cxx_compiler_flag_if_supported(-fstack-protector) endif() +eth_add_cxx_compiler_flag_if_supported(-Wimplicit-fallthrough) + if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) # Use ISO C++11 standard language. @@ -83,12 +80,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () - # Until https://github.com/ethereum/solidity/issues/2479 is handled - # disable all implicit fallthrough warnings in the codebase for GCC > 7.0 - if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0) - add_compile_options(-Wno-implicit-fallthrough) - endif() - # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") From ffd440ccffabebf161af7cc602fd0beb56350cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 26 Sep 2017 22:44:57 +0200 Subject: [PATCH 015/108] CMake: Cleanup include paths --- CMakeLists.txt | 2 +- cmake/EthBuildInfo.cmake | 2 +- cmake/EthDependencies.cmake | 7 ------- libevmasm/CMakeLists.txt | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f71cedce7de..537a95212e42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ string(REGEX MATCHALL ".." LICENSE_TEXT "${LICENSE_TEXT}") string(REGEX REPLACE ";" ",\n\t0x" LICENSE_TEXT "${LICENSE_TEXT}") set(LICENSE_TEXT "0x${LICENSE_TEXT}") -configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" "license.h") +configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" include/license.h) include(EthOptions) configure_project(TESTS) diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake index 1f70d3719677..cae3e5cef344 100644 --- a/cmake/EthBuildInfo.cmake +++ b/cmake/EthBuildInfo.cmake @@ -39,5 +39,5 @@ function(create_build_info NAME) -DPROJECT_VERSION="${PROJECT_VERSION}" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" ) - include_directories(BEFORE ${PROJECT_BINARY_DIR}) + include_directories("${PROJECT_BINARY_DIR}/include") endfunction() diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 1204f1861918..233ac22a27e1 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -48,10 +48,3 @@ option(Boost_USE_STATIC_LIBS "Link Boost statically" ON) find_package(Boost 1.54.0 QUIET REQUIRED COMPONENTS regex filesystem unit_test_framework program_options system) eth_show_dependency(Boost boost) - -if (APPLE) - link_directories(/usr/local/lib) - include_directories(/usr/local/include) -endif() - -include_directories(BEFORE "${PROJECT_BINARY_DIR}/include") diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 5c945c7d4688..cfd59dff4c4d 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -2,4 +2,4 @@ file(GLOB sources "*.cpp") file(GLOB headers "*.h") add_library(evmasm ${sources} ${headers}) -target_link_libraries(evmasm PUBLIC devcore jsoncpp) +target_link_libraries(evmasm PUBLIC jsoncpp devcore) From ee65ecfb3b80d9c027bade21df883e897b1234c5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 26 Sep 2017 22:46:33 +0100 Subject: [PATCH 016/108] Ensure that address types are always declared as 160bit --- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/ast/Types.cpp | 14 +++++++------- libsolidity/codegen/ABIFunctions.cpp | 4 ++-- libsolidity/codegen/CompilerUtils.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4b2ec8d64233..21d3dda6c2de 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1954,7 +1954,7 @@ void TypeChecker::endVisit(Literal const& _literal) if (_literal.looksLikeAddress()) { if (_literal.passesAddressChecksum()) - _literal.annotation().type = make_shared(0, IntegerType::Modifier::Address); + _literal.annotation().type = make_shared(160, IntegerType::Modifier::Address); else m_errorReporter.warning( _literal.location(), diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 83a5b465afc2..ebf2cd8b34b3 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -203,7 +203,7 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) case Token::Byte: return make_shared(1); case Token::Address: - return make_shared(0, IntegerType::Modifier::Address); + return make_shared(160, IntegerType::Modifier::Address); case Token::Bool: return make_shared(); case Token::Bytes: @@ -327,11 +327,11 @@ IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): m_bits(_bits), m_modifier(_modifier) { if (isAddress()) - m_bits = 160; + solAssert(m_bits == 160, ""); solAssert( m_bits > 0 && m_bits <= 256 && m_bits % 8 == 0, "Invalid bit number for integer type: " + dev::toString(_bits) - ); + ); } string IntegerType::identifier() const @@ -1619,7 +1619,7 @@ string ContractType::canonicalName() const MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const { // All address members and all interface functions - MemberList::MemberMap members(IntegerType(120, IntegerType::Modifier::Address).nativeMembers(nullptr)); + MemberList::MemberMap members(IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr)); if (m_super) { // add the most derived of all functions which are visible in derived contracts @@ -2968,7 +2968,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const { case Kind::Block: return MemberList::MemberMap({ - {"coinbase", make_shared(0, IntegerType::Modifier::Address)}, + {"coinbase", make_shared(160, IntegerType::Modifier::Address)}, {"timestamp", make_shared(256)}, {"blockhash", make_shared(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)}, {"difficulty", make_shared(256)}, @@ -2977,7 +2977,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const }); case Kind::Message: return MemberList::MemberMap({ - {"sender", make_shared(0, IntegerType::Modifier::Address)}, + {"sender", make_shared(160, IntegerType::Modifier::Address)}, {"gas", make_shared(256)}, {"value", make_shared(256)}, {"data", make_shared(DataLocation::CallData)}, @@ -2985,7 +2985,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const }); case Kind::Transaction: return MemberList::MemberMap({ - {"origin", make_shared(0, IntegerType::Modifier::Address)}, + {"origin", make_shared(160, IntegerType::Modifier::Address)}, {"gasprice", make_shared(256)} }); default: diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 9f6c55ba6702..22b620e1a3de 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -162,7 +162,7 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) break; } case Type::Category::Contract: - templ("body", "cleaned := " + cleanupFunction(IntegerType(0, IntegerType::Modifier::Address)) + "(value)"); + templ("body", "cleaned := " + cleanupFunction(IntegerType(160, IntegerType::Modifier::Address)) + "(value)"); break; case Type::Category::Enum: { @@ -243,7 +243,7 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) toCategory == Type::Category::Integer || toCategory == Type::Category::Contract, ""); - IntegerType const addressType(0, IntegerType::Modifier::Address); + IntegerType const addressType(160, IntegerType::Modifier::Address); IntegerType const& to = toCategory == Type::Category::Integer ? dynamic_cast(_to) : diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index c1171c1d2b1c..ce97ed610c68 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -541,7 +541,7 @@ void CompilerUtils::convertType( else { solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); - IntegerType addressType(0, IntegerType::Modifier::Address); + IntegerType addressType(160, IntegerType::Modifier::Address); IntegerType const& targetType = targetTypeCategory == Type::Category::Integer ? dynamic_cast(_targetType) : addressType; if (stackTypeCategory == Type::Category::RationalNumber) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b286594ab932..58c64bce72fe 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1040,7 +1040,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) identifier = FunctionType(*function).externalIdentifier(); else solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, IntegerType(0, IntegerType::Modifier::Address), true); + utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true); m_context << identifier; } else @@ -1057,7 +1057,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { utils().convertType( *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), + IntegerType(160, IntegerType::Modifier::Address), true ); m_context << Instruction::BALANCE; @@ -1065,7 +1065,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else if ((set{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) utils().convertType( *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), + IntegerType(160, IntegerType::Modifier::Address), true ); else From a7592fa8016401b4674faa5059b0ae00dc7ece68 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 26 Sep 2017 21:21:49 +0100 Subject: [PATCH 017/108] Document packed ABI --- docs/abi-spec.rst | 19 +++++++++++++++++++ docs/miscellaneous.rst | 6 +++--- docs/units-and-global-variables.rst | 6 +++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 29d98645ec06..0361458f8bd3 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -442,3 +442,22 @@ would result in the JSON: "outputs": [] } ] + +.. _abi_packed_mode: + +Non-standard Packed Mode +======================== + +Solidity supports a non-standard packed mode where: + +- no :ref:`function selector ` is encoded, +- short types are not zero padded and +- dynamic types are encoded in-place and without the length. + +As an example encoding ``uint1, bytes1, uint8, string`` with values ``1, 0x42, 0x2424, "Hello, world!"`` results in :: + + 0x0142242448656c6c6f2c20776f726c6421 + ^^ uint1(1) + ^^ bytes1(0x42) + ^^^^ uint8(0x2424) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 6d6c25acb908..6c0efa9efa6f 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -322,10 +322,10 @@ Global Variables - ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) - ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component) - ``revert()``: abort execution and revert state changes -- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments +- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments ` - ``sha3(...) returns (bytes32)``: an alias to ``keccak256`` -- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the (tightly packed) arguments -- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the (tightly packed) arguments +- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments ` +- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments ` - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256`` - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256`` diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 887535da72d9..7af97376f2bb 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -116,13 +116,13 @@ Mathematical and Cryptographic Functions ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. ``keccak256(...) returns (bytes32)``: - compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments + compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments ` ``sha256(...) returns (bytes32)``: - compute the SHA-256 hash of the (tightly packed) arguments + compute the SHA-256 hash of the :ref:`(tightly packed) arguments ` ``sha3(...) returns (bytes32)``: alias to ``keccak256`` ``ripemd160(...) returns (bytes20)``: - compute RIPEMD-160 hash of the (tightly packed) arguments + compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments ` ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover the address associated with the public key from elliptic curve signature or return zero on error (`example usage `_) From 9ea812598d5217372fc27a906e99a78bf7b490f1 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 25 Sep 2017 14:12:39 +0100 Subject: [PATCH 018/108] Fix other test to use ABI_CHECK --- test/libsolidity/SolidityEndToEndTest.cpp | 48 ++++++++++++----------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 0536626fafda..df9332c401b5 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1494,7 +1494,7 @@ BOOST_AUTO_TEST_CASE(now) size_t endTime = blockTimestamp(endBlock); BOOST_CHECK(startBlock != endBlock); BOOST_CHECK(startTime != endTime); - BOOST_CHECK(ret == encodeArgs(true, endTime)); + ABI_CHECK(ret, encodeArgs(true, endTime)); } BOOST_AUTO_TEST_CASE(type_conversions_cleanup) @@ -5185,7 +5185,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_signed) } )"; compileAndRun(sourceCode); - BOOST_CHECK( callContractFunction("test()") == encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); } BOOST_AUTO_TEST_CASE(external_types_in_calls) @@ -5540,7 +5540,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) } } )"; - BOOST_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A").empty()); + ABI_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A"), encodeArgs()); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed) @@ -6505,31 +6505,32 @@ BOOST_AUTO_TEST_CASE(string_as_mapping_key) "1" }; for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "set(string,uint256)", u256(0x40), u256(7 + i), u256(strings[i].size()), strings[i] - ) == encodeArgs()); + ), encodeArgs()); for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "get(string)", u256(0x20), u256(strings[i].size()), strings[i] - ) == encodeArgs(u256(7 + i))); + ), encodeArgs(u256(7 + i))); } BOOST_AUTO_TEST_CASE(accessor_for_state_variable) { char const* sourceCode = R"( - contract Lotto{ + contract Lotto { uint public ticketPrice = 500; - })"; + } + )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); } BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) @@ -6537,10 +6538,11 @@ BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) char const* sourceCode = R"( contract Lotto{ uint constant public ticketPrice = 555; - })"; + } + )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); } BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) @@ -7913,7 +7915,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) @@ -8776,8 +8778,8 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK( - callContractFunction("f()") == + ABI_CHECK( + callContractFunction("f()"), m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) ); } @@ -10120,9 +10122,9 @@ BOOST_AUTO_TEST_CASE(function_types_sig) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); } BOOST_AUTO_TEST_CASE(constant_string) @@ -10144,9 +10146,9 @@ BOOST_AUTO_TEST_CASE(constant_string) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("g()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("h()") == encodeDyn(string("hello"))); + ABI_CHECK(callContractFunction("f()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("g()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello"))); } BOOST_AUTO_TEST_SUITE_END() From dcb61352f6cadac4f036fa39927729781db303c5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 Sep 2017 10:21:24 +0100 Subject: [PATCH 019/108] Report correct location for inferred types in packed encoding --- libsolidity/analysis/TypeChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4b2ec8d64233..66ece478c2a6 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1497,7 +1497,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) /* If no mobile type is available an error will be raised elsewhere. */ if (literal->mobileType()) m_errorReporter.warning( - _functionCall.location(), + arguments[i]->location(), "The type of \"" + argType->toString() + "\" was inferred as " + From a657d3b1a165d9ec14f9875db2380954f9ca37cf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 26 Sep 2017 18:50:43 +0100 Subject: [PATCH 020/108] Make most of the parameters mandatory in encodeToMemory --- libsolidity/codegen/CompilerUtils.h | 8 ++++---- libsolidity/codegen/ExpressionCompiler.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 5e45699be9f6..b239bde67cb0 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -102,10 +102,10 @@ class CompilerUtils /// @note the locations of target reference types are ignored, because it will always be /// memory. void encodeToMemory( - TypePointers const& _givenTypes = {}, - TypePointers const& _targetTypes = {}, - bool _padToWords = true, - bool _copyDynamicDataInPlace = false, + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _padToWords, + bool _copyDynamicDataInPlace, bool _encodeAsLibraryTypes = false ); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 58c64bce72fe..5de24136fed6 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -581,7 +581,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) _context << Instruction::ADD; } ); - utils().encodeToMemory(argumentTypes, function.parameterTypes()); + utils().encodeToMemory(argumentTypes, function.parameterTypes(), true, false); // now on stack: memory_end_ptr // need: size, offset, endowment utils().toSizeAfterFreeMemoryPointer(); @@ -751,7 +751,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) nonIndexedParamTypes.push_back(function.parameterTypes()[arg]); } utils().fetchFreeMemoryPointer(); - utils().encodeToMemory(nonIndexedArgTypes, nonIndexedParamTypes); + utils().encodeToMemory(nonIndexedArgTypes, nonIndexedParamTypes, true, false); // need: topic1 ... topicn memsize memstart utils().toSizeAfterFreeMemoryPointer(); m_context << logInstruction(numIndexed); From 82673b7b3fefbacf4f1ffae7b53414eea6310b44 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 26 Sep 2017 21:48:59 +0100 Subject: [PATCH 021/108] Format GlobalContext for readability --- libsolidity/analysis/GlobalContext.cpp | 67 ++++++++++---------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 62dbd394373f..624cc9576914 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -34,44 +34,29 @@ namespace solidity { GlobalContext::GlobalContext(): -m_magicVariables(vector>{make_shared("block", make_shared(MagicType::Kind::Block)), - make_shared("msg", make_shared(MagicType::Kind::Message)), - make_shared("tx", make_shared(MagicType::Kind::Transaction)), - make_shared("now", make_shared(256)), - make_shared("suicide", - make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared("selfdestruct", - make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared("addmod", - make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), - make_shared("mulmod", - make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), - make_shared("sha3", - make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), - make_shared("keccak256", - make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), - make_shared("log0", - make_shared(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), - make_shared("log1", - make_shared(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), - make_shared("log2", - make_shared(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), - make_shared("log3", - make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), - make_shared("log4", - make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), - make_shared("sha256", - make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), - make_shared("ecrecover", - make_shared(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), - make_shared("ripemd160", - make_shared(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), - make_shared("assert", - make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), - make_shared("require", - make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), - make_shared("revert", - make_shared(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure))}) +m_magicVariables(vector>{ + make_shared("block", make_shared(MagicType::Kind::Block)), + make_shared("msg", make_shared(MagicType::Kind::Message)), + make_shared("tx", make_shared(MagicType::Kind::Transaction)), + make_shared("now", make_shared(256)), + make_shared("suicide", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared("selfdestruct", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared("addmod", make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), + make_shared("mulmod", make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), + make_shared("sha3", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared("keccak256", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared("log0", make_shared(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), + make_shared("log1", make_shared(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), + make_shared("log2", make_shared(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), + make_shared("log3", make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), + make_shared("log4", make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), + make_shared("sha256", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), + make_shared("ecrecover", make_shared(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), + make_shared("ripemd160", make_shared(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), + make_shared("assert", make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), + make_shared("require", make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), + make_shared("revert", make_shared(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)) +}) { } @@ -92,8 +77,7 @@ vector GlobalContext::declarations() const MagicVariableDeclaration const* GlobalContext::currentThis() const { if (!m_thisPointer[m_currentContract]) - m_thisPointer[m_currentContract] = make_shared( - "this", make_shared(*m_currentContract)); + m_thisPointer[m_currentContract] = make_shared("this", make_shared(*m_currentContract)); return m_thisPointer[m_currentContract].get(); } @@ -101,8 +85,7 @@ MagicVariableDeclaration const* GlobalContext::currentThis() const MagicVariableDeclaration const* GlobalContext::currentSuper() const { if (!m_superPointer[m_currentContract]) - m_superPointer[m_currentContract] = make_shared( - "super", make_shared(*m_currentContract, true)); + m_superPointer[m_currentContract] = make_shared("super", make_shared(*m_currentContract, true)); return m_superPointer[m_currentContract].get(); } From 0dda5eeca3873670a4963fafa77d6a4389519d21 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 Sep 2017 00:39:57 +0100 Subject: [PATCH 022/108] Order GlobalContext entries --- libsolidity/analysis/GlobalContext.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 624cc9576914..fd39d860d09d 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -35,27 +35,27 @@ namespace solidity GlobalContext::GlobalContext(): m_magicVariables(vector>{ - make_shared("block", make_shared(MagicType::Kind::Block)), - make_shared("msg", make_shared(MagicType::Kind::Message)), - make_shared("tx", make_shared(MagicType::Kind::Transaction)), - make_shared("now", make_shared(256)), - make_shared("suicide", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared("selfdestruct", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), make_shared("addmod", make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), - make_shared("mulmod", make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), - make_shared("sha3", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared("assert", make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), + make_shared("block", make_shared(MagicType::Kind::Block)), + make_shared("ecrecover", make_shared(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), make_shared("keccak256", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), make_shared("log0", make_shared(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), make_shared("log1", make_shared(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), make_shared("log2", make_shared(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), make_shared("log3", make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), make_shared("log4", make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), - make_shared("sha256", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), - make_shared("ecrecover", make_shared(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), - make_shared("ripemd160", make_shared(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), - make_shared("assert", make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), + make_shared("msg", make_shared(MagicType::Kind::Message)), + make_shared("mulmod", make_shared(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), + make_shared("now", make_shared(256)), make_shared("require", make_shared(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), - make_shared("revert", make_shared(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)) + make_shared("revert", make_shared(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), + make_shared("ripemd160", make_shared(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), + make_shared("selfdestruct", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared("sha256", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), + make_shared("sha3", make_shared(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared("suicide", make_shared(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared("tx", make_shared(MagicType::Kind::Transaction)) }) { } From 204214f0700179e3d8fa97c77d4f92acd349f015 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 26 Sep 2017 22:10:30 +0100 Subject: [PATCH 023/108] Split encodeToMemory to packedEncode and abiEncode --- libsolidity/codegen/CompilerUtils.cpp | 4 ++-- libsolidity/codegen/CompilerUtils.h | 27 ++++++++++++++++++++++ libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 26 +++++++++------------ 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index ce97ed610c68..f9b181aed26d 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -191,7 +191,7 @@ void CompilerUtils::encodeToMemory( { // Use the new JULIA-based encoding function auto stackHeightBefore = m_context.stackHeight(); - abiEncode(_givenTypes, targetTypes, _encodeAsLibraryTypes); + abiEncodeV2(_givenTypes, targetTypes, _encodeAsLibraryTypes); solAssert(stackHeightBefore - m_context.stackHeight() == sizeOnStack(_givenTypes), ""); return; } @@ -302,7 +302,7 @@ void CompilerUtils::encodeToMemory( popStackSlots(argSize + dynPointers + 1); } -void CompilerUtils::abiEncode( +void CompilerUtils::abiEncodeV2( TypePointers const& _givenTypes, TypePointers const& _targetTypes, bool _encodeAsLibraryTypes diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index b239bde67cb0..ad3989adfca1 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -109,6 +109,19 @@ class CompilerUtils bool _encodeAsLibraryTypes = false ); + /// Special case of @a encodeToMemory which assumes tight packing, e.g. no zero padding + /// and dynamic data is encoded in-place. + /// Stack pre: ... + /// Stack post: + void packedEncode( + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _encodeAsLibraryTypes = false + ) + { + encodeToMemory(_givenTypes, _targetTypes, false, true, _encodeAsLibraryTypes); + } + /// Special case of @a encodeToMemory which assumes that everything is padded to words /// and dynamic data is not copied in place (i.e. a proper ABI encoding). /// Stack pre: ... @@ -117,6 +130,20 @@ class CompilerUtils TypePointers const& _givenTypes, TypePointers const& _targetTypes, bool _encodeAsLibraryTypes = false + ) + { + encodeToMemory(_givenTypes, _targetTypes, true, false, _encodeAsLibraryTypes); + } + + /// Special case of @a encodeToMemory which assumes that everything is padded to words + /// and dynamic data is not copied in place (i.e. a proper ABI encoding). + /// Uses a new, less tested encoder implementation. + /// Stack pre: ... + /// Stack post: + void abiEncodeV2( + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _encodeAsLibraryTypes = false ); /// Zero-initialises (the data part of) an already allocated memory array. diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 92782b8d7dcc..429db5327c03 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -421,7 +421,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete utils.fetchFreeMemoryPointer(); //@todo optimization: if we return a single memory array, there should be enough space before // its data to add the needed parts and we avoid a memory copy. - utils.encodeToMemory(_typeParameters, _typeParameters, true, false, _isLibrary); + utils.abiEncode(_typeParameters, _typeParameters, _isLibrary); utils.toSizeAfterFreeMemoryPointer(); m_context << Instruction::RETURN; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 5de24136fed6..c2bf0f5cdf81 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -581,7 +581,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) _context << Instruction::ADD; } ); - utils().encodeToMemory(argumentTypes, function.parameterTypes(), true, false); + utils().abiEncode(argumentTypes, function.parameterTypes()); // now on stack: memory_end_ptr // need: size, offset, endowment utils().toSizeAfterFreeMemoryPointer(); @@ -675,7 +675,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) argumentTypes.push_back(arg->annotation().type); } utils().fetchFreeMemoryPointer(); - utils().encodeToMemory(argumentTypes, TypePointers(), function.padArguments(), true); + solAssert(!function.padArguments(), ""); + utils().packedEncode(argumentTypes, TypePointers()); utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; break; @@ -694,11 +695,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } arguments.front()->accept(*this); utils().fetchFreeMemoryPointer(); - utils().encodeToMemory( + utils().packedEncode( {arguments.front()->annotation().type}, - {function.parameterTypes().front()}, - false, - true); + {function.parameterTypes().front()} + ); utils().toSizeAfterFreeMemoryPointer(); m_context << logInstruction(logNumber); break; @@ -717,11 +717,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) if (auto const& arrayType = dynamic_pointer_cast(function.parameterTypes()[arg - 1])) { utils().fetchFreeMemoryPointer(); - utils().encodeToMemory( + utils().packedEncode( {arguments[arg - 1]->annotation().type}, - {arrayType}, - false, - true + {arrayType} ); utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; @@ -751,7 +749,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) nonIndexedParamTypes.push_back(function.parameterTypes()[arg]); } utils().fetchFreeMemoryPointer(); - utils().encodeToMemory(nonIndexedArgTypes, nonIndexedParamTypes, true, false); + utils().abiEncode(nonIndexedArgTypes, nonIndexedParamTypes); // need: topic1 ... topicn memsize memstart utils().toSizeAfterFreeMemoryPointer(); m_context << logInstruction(numIndexed); @@ -1212,11 +1210,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) utils().fetchFreeMemoryPointer(); // stack: base index mem // note: the following operations must not allocate memory! - utils().encodeToMemory( + utils().packedEncode( TypePointers{_indexAccess.indexExpression()->annotation().type}, - TypePointers{keyType}, - false, - true + TypePointers{keyType} ); m_context << Instruction::SWAP1; utils().storeInMemoryDynamic(IntegerType(256)); From 2940964044331a87cbc3573fdb80fda8f0b4e976 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 27 Sep 2017 15:56:17 +0200 Subject: [PATCH 024/108] ABI encoder fixes and test. --- libsolidity/codegen/ABIFunctions.cpp | 7 +--- test/libsolidity/ABIEncoderTests.cpp | 59 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 22b620e1a3de..202a747f18f2 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -538,7 +538,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( mstore(pos, sub(tail, headStart)) tail := (, tail) srcPtr := (srcPtr) - pos := add(pos, ) + pos := add(pos, 0x20) } pos := tail @@ -832,7 +832,7 @@ string ABIFunctions::abiEncodingFunctionStruct( } memberTempl("encodingOffset", toCompactHexWithPrefix(encodingOffset)); encodingOffset += dynamicMember ? 0x20 : memberTypeTo->calldataEncodedSize(); - memberTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, _encodeAsLibraryTypes, false)); + memberTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, _encodeAsLibraryTypes, true)); members.push_back({}); members.back()["encode"] = memberTempl.render(); @@ -1190,10 +1190,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes) if (t->isDynamicallyEncoded()) headSize += 0x20; else - { - solAssert(t->calldataEncodedSize() > 0, ""); headSize += t->calldataEncodedSize(); - } } return headSize; diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 05158601f4ba..9836eb779ae5 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -462,6 +462,65 @@ BOOST_AUTO_TEST_CASE(structs) ) } +BOOST_AUTO_TEST_CASE(structs2) +{ + string sourceCode = R"( + contract C { + enum E {A, B, C} + struct T { uint x; E e; uint8 y; } + struct S { C c; T[] t;} + function f() public returns (uint a, S[2] s1, S[] s2, uint b) { + a = 7; + b = 8; + s1[0].c = this; + s1[0].t = new T[](1); + s1[0].t[0].x = 0x11; + s1[0].t[0].e = E.B; + s1[0].t[0].y = 0x12; + s2 = new S[](2); + s2[1].c = C(0x1234); + s2[1].t = new T[](3); + s2[1].t[1].x = 0x21; + s2[1].t[1].e = E.C; + s2[1].t[1].y = 0x22; + } + } + )"; + + NEW_ENCODER( + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 7, 0x80, 0x1e0, 8, + // S[2] s1 + 0x40, + 0x100, + // S s1[0] + u256(u160(m_contractAddress)), + 0x40, + // T s1[0].t + 1, // length + // s1[0].t[0] + 0x11, 1, 0x12, + // S s1[1] + 0, 0x40, + // T s1[1].t + 0, + // S[] s2 (0x1e0) + 2, // length + 0x40, 0xa0, + // S s2[0] + 0, 0x40, 0, + // S s2[1] + 0x1234, 0x40, + // s2[1].t + 3, // length + 0, 0, 0, + 0x21, 2, 0x22, + 0, 0, 0 + )); + ) +} + BOOST_AUTO_TEST_SUITE_END() } From 3ebe29a031e56eb9e139848bbee3067a71a28ce7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 27 Sep 2017 15:56:58 +0200 Subject: [PATCH 025/108] Better readable encoder assembly. --- libsolidity/codegen/ABIFunctions.cpp | 34 +++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 22b620e1a3de..756148e7787a 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -487,6 +487,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArray( // TODO if this is not a byte array, we might just copy byte-by-byte anyway, // because the encoding is position-independent, but we have to check that. Whiskers templ(R"( + // -> function (start, length, pos) -> end { // might update pos (start, pos, length) @@ -495,6 +496,8 @@ string ABIFunctions::abiEncodingFunctionCalldataArray( )"); templ("storeLength", _to.isDynamicallySized() ? "mstore(pos, length) pos := add(pos, 0x20)" : ""); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("copyFun", copyToMemoryFunction(true)); templ("roundUpFun", roundUpFunction()); return templ.render(); @@ -527,6 +530,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( Whiskers templ( dynamicBase ? R"( + // -> function (value, pos) { let length := (value) // might update pos @@ -545,6 +549,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( } )" : R"( + // -> function (value, pos) { let length := (value) // might update pos @@ -560,6 +565,8 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( )" ); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := pos" : ""); templ("lengthFun", arrayLengthFunction(_from)); @@ -639,6 +646,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( { solAssert(_to.isByteArray(), ""); Whiskers templ(R"( + // -> function (value, pos) -> ret { let slotValue := sload(value) switch and(slotValue, 1) @@ -665,6 +673,8 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( } )"); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("arrayDataSlot", arrayDataAreaFunction(_from)); return templ.render(); } @@ -681,6 +691,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( // more than desired, i.e. it writes beyond the end of memory. Whiskers templ( R"( + // -> function (value, pos) { let length := (value) // might update pos @@ -701,6 +712,8 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( )" ); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := pos" : ""); templ("lengthFun", arrayLengthFunction(_from)); @@ -748,6 +761,7 @@ string ABIFunctions::abiEncodingFunctionStruct( bool fromStorage = _from.location() == DataLocation::Storage; bool dynamic = _to.isDynamicallyEncoded(); Whiskers templ(R"( + // -> function (value, pos) { let tail := add(pos, ) @@ -761,6 +775,8 @@ string ABIFunctions::abiEncodingFunctionStruct( } )"); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := tail" : ""); // to avoid multiple loads from the same slot for subsequent members @@ -995,9 +1011,11 @@ string ABIFunctions::shiftLeftFunction(size_t _numBits) return createFunction(functionName, [&]() { solAssert(_numBits < 256, ""); return - Whiskers(R"(function (value) -> newValue { + Whiskers(R"( + function (value) -> newValue { newValue := mul(value, ) - })") + } + )") ("functionName", functionName) ("multiplier", toCompactHexWithPrefix(u256(1) << _numBits)) .render(); @@ -1010,9 +1028,11 @@ string ABIFunctions::shiftRightFunction(size_t _numBits, bool _signed) return createFunction(functionName, [&]() { solAssert(_numBits < 256, ""); return - Whiskers(R"(function (value) -> newValue { + Whiskers(R"( + function (value) -> newValue { newValue :=
(value, ) - })") + } + )") ("functionName", functionName) ("div", _signed ? "sdiv" : "div") ("multiplier", toCompactHexWithPrefix(u256(1) << _numBits)) @@ -1025,9 +1045,11 @@ string ABIFunctions::roundUpFunction() string functionName = "round_up_to_mul_of_32"; return createFunction(functionName, [&]() { return - Whiskers(R"(function (value) -> result { + Whiskers(R"( + function (value) -> result { result := and(add(value, 31), not(31)) - })") + } + )") ("functionName", functionName) .render(); }); From acd70557ccb6e86bcbfb14197f30a285d9992d6b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 27 Sep 2017 17:55:04 +0200 Subject: [PATCH 026/108] Test encoder for empty structs. --- test/libsolidity/ABIEncoderTests.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 9836eb779ae5..af51edcc6977 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -462,6 +462,28 @@ BOOST_AUTO_TEST_CASE(structs) ) } +BOOST_AUTO_TEST_CASE(empty_struct) +{ + string sourceCode = R"( + contract C { + struct S { } + S s; + event e(uint16, S, uint16); + function f() returns (uint, S, uint) { + e(7, s, 8); + return (7, s, 8); + } + } + )"; + + NEW_ENCODER( + compileAndRun(sourceCode, 0, "C"); + bytes encoded = encodeArgs(7, 8); + BOOST_CHECK(callContractFunction("f()") == encoded); + REQUIRE_LOG_DATA(encoded); + ) +} + BOOST_AUTO_TEST_CASE(structs2) { string sourceCode = R"( From ab4f97a80b05c1e707dd1a8572657b76e94804c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Wed, 27 Sep 2017 13:59:26 -0300 Subject: [PATCH 027/108] Update contracts.rst Fixed web3 URL --- docs/contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index 69600fc165f6..cdc9231539eb 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -20,7 +20,7 @@ Contracts can be created "from outside" via Ethereum transactions or from within IDEs, such as `Remix `_, make the creation process seamless using UI elements. -Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js `_. +Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js `_. As of today it has a method called `web3.eth.Contract `_ to facilitate contract creation. From 639b85f4987db13bebdd751b205424810a7daab7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 27 Sep 2017 19:27:36 +0200 Subject: [PATCH 028/108] Fix source location of VariableDeclarationStatement. --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 9755d2d361af..b16438109ce1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Features: * Parser: Better error message for unexpected trailing comma in parameter lists. Bugfixes: + * Parser: Fix source location of VariableDeclarationStatement. ### 0.4.17 (2017-09-21) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 9a8bb3585ba5..821e81d22353 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1133,6 +1133,7 @@ ASTPointer Parser::parseVariableDeclarationStateme options.allowVar = true; options.allowLocationSpecifier = true; variables.push_back(parseVariableDeclaration(options, _lookAheadArrayType)); + nodeFactory.setEndPositionFromNode(variables.back()); } if (m_scanner->currentToken() == Token::Assign) { From c6c3163c2a2e3dbe30a9ee51773cc652de026c01 Mon Sep 17 00:00:00 2001 From: Zetherz <32152358+zetherz@users.noreply.github.com> Date: Thu, 28 Sep 2017 07:21:02 -0500 Subject: [PATCH 029/108] Fixed code example (#2955) --- docs/frequently-asked-questions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 93dcfbb815a0..5c427c692ec3 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -432,12 +432,12 @@ What happens to a ``struct``'s mapping when copying over a ``struct``? This is a very interesting question. Suppose that we have a contract field set up like such:: struct user { - mapping(string => address) usedContracts; + mapping(string => string) comments; } function somefunction { user user1; - user1.usedContracts["Hello"] = "World"; + user1.comments["Hello"] = "World"; user user2 = user1; } From 7cb4d714c7e058ab764b14575fc32078a0343fbc Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 20 Sep 2017 11:14:28 +0100 Subject: [PATCH 030/108] Fix overload resolution when conflict is with members of address (balance, transfer, etc) --- Changelog.md | 2 ++ libsolidity/analysis/TypeChecker.cpp | 34 +++++++++++++++---- test/libsolidity/SolidityEndToEndTest.cpp | 25 ++++++++++++++ .../SolidityNameAndTypeResolution.cpp | 23 +++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index b16438109ce1..a83c6ddb184e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,8 @@ Features: Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. + * Type Checker: Properly support overwriting members inherited from ``address`` in a contract + (such as ``balance``, ``transfer``, etc.) ### 0.4.17 (2017-09-21) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4393012522a8..43a77002d281 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1720,12 +1720,34 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ); } else if (possibleMembers.size() > 1) - m_errorReporter.fatalTypeError( - _memberAccess.location(), - "Member \"" + memberName + "\" not unique " - "after argument-dependent lookup in " + exprType->toString() + - (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "") - ); + { + // Remove builtins (i.e. not having a declaration) first + for (auto it = possibleMembers.begin(); it != possibleMembers.end();) + if ( + ( + // Overloaded functions without declaration (e.g. transfer(), send(), call(), etc.) + it->type->category() == Type::Category::Function && + !dynamic_cast(*it->type).hasDeclaration() + ) + || + ( + // Overloaded members (e.g. balance) + it->type->category() == Type::Category::Integer && + memberName == "balance" + ) + ) + it = possibleMembers.erase(it); + else + ++it; + + if (possibleMembers.size() > 1) + m_errorReporter.fatalTypeError( + _memberAccess.location(), + "Member \"" + memberName + "\" not unique " + "after argument-dependent lookup in " + exprType->toString() + + (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "") + ); + } auto& annotation = _memberAccess.annotation(); annotation.referencedDeclaration = possibleMembers.front().declaration; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index df9332c401b5..35916ec7f9eb 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10151,6 +10151,31 @@ BOOST_AUTO_TEST_CASE(constant_string) ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello"))); } +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* sourceCode = R"( + contract C { + function balance() returns (uint) { + return 1; + } + function transfer(uint amount) returns (uint) { + return amount; + } + } + contract D { + function f() returns (uint) { + return (new C()).balance(); + } + function g() returns (uint) { + return (new C()).transfer(5); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 39c47f9c54bb..959bc4ffc8a2 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6953,6 +6953,29 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide) CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* text = R"( + contract C { + function balance() returns (uint) { + this.balance; // to avoid pureness warning + return 1; + } + function transfer(uint amount) { + address(this).transfer(amount); // to avoid pureness warning + } + } + contract D { + function f() { + var x = (new C()).balance(); + x; + (new C()).transfer(5); + } + } + )"; + CHECK_SUCCESS(text); +} + BOOST_AUTO_TEST_SUITE_END() } From aa6de494577e18dcca228df1f206e6dcbcd47902 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 25 Sep 2017 12:58:32 +0100 Subject: [PATCH 031/108] Simplify address overloading --- libsolidity/analysis/TypeChecker.cpp | 34 +++++---------------------- libsolidity/ast/Types.cpp | 35 ++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 43a77002d281..4393012522a8 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1720,34 +1720,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ); } else if (possibleMembers.size() > 1) - { - // Remove builtins (i.e. not having a declaration) first - for (auto it = possibleMembers.begin(); it != possibleMembers.end();) - if ( - ( - // Overloaded functions without declaration (e.g. transfer(), send(), call(), etc.) - it->type->category() == Type::Category::Function && - !dynamic_cast(*it->type).hasDeclaration() - ) - || - ( - // Overloaded members (e.g. balance) - it->type->category() == Type::Category::Integer && - memberName == "balance" - ) - ) - it = possibleMembers.erase(it); - else - ++it; - - if (possibleMembers.size() > 1) - m_errorReporter.fatalTypeError( - _memberAccess.location(), - "Member \"" + memberName + "\" not unique " - "after argument-dependent lookup in " + exprType->toString() + - (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "") - ); - } + m_errorReporter.fatalTypeError( + _memberAccess.location(), + "Member \"" + memberName + "\" not unique " + "after argument-dependent lookup in " + exprType->toString() + + (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "") + ); auto& annotation = _memberAccess.annotation(); annotation.referencedDeclaration = possibleMembers.front().declaration; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ebf2cd8b34b3..1a9a374f3df5 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1618,8 +1618,7 @@ string ContractType::canonicalName() const MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const { - // All address members and all interface functions - MemberList::MemberMap members(IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr)); + MemberList::MemberMap members; if (m_super) { // add the most derived of all functions which are visible in derived contracts @@ -1661,6 +1660,38 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con &it.second->declaration() )); } + // Add overloads from address only if there is no conflict + MemberList::MemberMap addressMembers = IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr); + for (auto const& addressMember: addressMembers) + { + bool clash = false; + for (auto const& member: members) + { + if ( + member.name == addressMember.name && + ( + // Members with different types are not allowed + member.type->category() != addressMember.type->category() || + // Members must overload functions without clash + ( + member.type->category() == Type::Category::Function && + dynamic_cast(*member.type).hasEqualArgumentTypes(dynamic_cast(*addressMember.type)) + ) + ) + ) + { + clash = true; + break; + } + } + + if (!clash) + members.push_back(MemberList::Member( + addressMember.name, + addressMember.type, + addressMember.declaration + )); + } return members; } From d5d1a08b09bec098851afc48fc0f115eac193955 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 28 Sep 2017 13:43:09 +0100 Subject: [PATCH 032/108] Pull out helper to apply address member to contract members --- libsolidity/ast/Types.cpp | 12 ++++++++---- libsolidity/ast/Types.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 1a9a374f3df5..a39b57758d5e 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1660,12 +1660,17 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con &it.second->declaration() )); } - // Add overloads from address only if there is no conflict + addNonConflictingAddressMembers(members); + return members; +} + +void ContractType::addNonConflictingAddressMembers(MemberList::MemberMap& _members) +{ MemberList::MemberMap addressMembers = IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr); for (auto const& addressMember: addressMembers) { bool clash = false; - for (auto const& member: members) + for (auto const& member: _members) { if ( member.name == addressMember.name && @@ -1686,13 +1691,12 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con } if (!clash) - members.push_back(MemberList::Member( + _members.push_back(MemberList::Member( addressMember.name, addressMember.type, addressMember.declaration )); } - return members; } shared_ptr const& ContractType::newExpressionType() const diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 8ba555215d49..ce29975e7ca8 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -716,6 +716,8 @@ class ContractType: public Type std::vector> stateVariables() const; private: + static void addNonConflictingAddressMembers(MemberList::MemberMap& _members); + ContractDefinition const& m_contract; /// If true, it is the "super" type of the current contract, i.e. it contains only inherited /// members. From 9d8edb46f24517dc5a0dbc0b496caad75cf39ca3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 10:59:02 +0200 Subject: [PATCH 033/108] Allow test frameworks to filter out some warnings. --- test/libsolidity/AnalysisFramework.cpp | 14 ++++++++++++-- test/libsolidity/AnalysisFramework.h | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 5f5f6411c584..67cc027e32b8 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -56,8 +56,18 @@ AnalysisFramework::parseAnalyseAndReturnError( for (auto const& currentError: m_compiler.errors()) { solAssert(currentError->comment(), ""); - if (currentError->comment()->find("This is a pre-release compiler version") == 0) - continue; + if (currentError->type() == Error::Type::Warning) + { + bool ignoreWarning = false; + for (auto const& filter: m_warningsToFilter) + if (currentError->comment()->find(filter) == 0) + { + ignoreWarning = true; + break; + } + if (ignoreWarning) + continue; + } if (_reportWarnings || (currentError->type() != Error::Type::Warning)) { diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index 172ae01b918a..07e28f2b5030 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -45,7 +45,7 @@ class AnalysisFramework { protected: - std::pair> + virtual std::pair> parseAnalyseAndReturnError( std::string const& _source, bool _reportWarnings = false, @@ -65,6 +65,7 @@ class AnalysisFramework std::string const& _signature ); + std::vector m_warningsToFilter = {"This is a pre-release compiler version"}; dev::solidity::CompilerStack m_compiler; }; From 08effa0af54647971415cb66dc9181afad9642ee Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 10:59:15 +0200 Subject: [PATCH 034/108] More verbose error messages. --- test/libsolidity/AnalysisFramework.cpp | 31 +++++++++++++++++--------- test/libsolidity/AnalysisFramework.h | 8 +++++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 67cc027e32b8..3bdc40a044b8 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -25,6 +25,8 @@ #include +#include + #include #include @@ -46,8 +48,7 @@ AnalysisFramework::parseAnalyseAndReturnError( m_compiler.addSource("", _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source); if (!m_compiler.parse()) { - printErrors(); - BOOST_ERROR("Parsing contract failed in analysis test suite."); + BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors()); } m_compiler.analyze(); @@ -73,8 +74,7 @@ AnalysisFramework::parseAnalyseAndReturnError( { if (firstError && !_allowMultipleErrors) { - printErrors(); - BOOST_FAIL("Multiple errors found."); + BOOST_FAIL("Multiple errors found: " + formatErrors()); } if (!firstError) firstError = currentError; @@ -88,7 +88,10 @@ SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) { auto sourceAndError = parseAnalyseAndReturnError(_source); BOOST_REQUIRE(!!sourceAndError.first); - BOOST_REQUIRE(!sourceAndError.second); + string message; + if (sourceAndError.second) + message = "Unexpected error: " + formatError(*sourceAndError.second); + BOOST_REQUIRE_MESSAGE(!sourceAndError.second, message); return sourceAndError.first; } @@ -101,17 +104,23 @@ Error AnalysisFramework::expectError(std::string const& _source, bool _warning, { auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple); BOOST_REQUIRE(!!sourceAndError.second); - BOOST_REQUIRE(!!sourceAndError.first); + BOOST_REQUIRE_MESSAGE(!!sourceAndError.first, "Expected error, but no error happened."); return *sourceAndError.second; } -void AnalysisFramework::printErrors() +string AnalysisFramework::formatErrors() { + string message; for (auto const& error: m_compiler.errors()) - SourceReferenceFormatter::printExceptionInformation( - std::cerr, - *error, - (error->type() == Error::Type::Warning) ? "Warning" : "Error", + message += formatError(*error); + return message; +} + +string AnalysisFramework::formatError(Error const& _error) +{ + return SourceReferenceFormatter::formatExceptionInformation( + _error, + (_error.type() == Error::Type::Warning) ? "Warning" : "Error", [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); } ); } diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index 07e28f2b5030..a566ba1d375f 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -57,7 +57,8 @@ class AnalysisFramework bool success(std::string const& _source); Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); - void printErrors(); + std::string formatErrors(); + std::string formatError(Error const& _error); static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name); static FunctionTypePointer retrieveFunctionBySignature( @@ -105,7 +106,10 @@ CHECK_ERROR_OR_WARNING(text, Warning, substring, true, true) do \ { \ auto sourceAndError = parseAnalyseAndReturnError((text), true); \ - BOOST_CHECK(sourceAndError.second == nullptr); \ + std::string message; \ + if (sourceAndError.second) \ + message = formatError(*sourceAndError.second); \ + BOOST_CHECK_MESSAGE(!sourceAndError.second, message); \ } \ while(0) From 5ee3ceaef77e5ab1fdcee1a698e5693823c14986 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 10:24:17 +0200 Subject: [PATCH 035/108] Remove leftover couts. --- libsolidity/formal/Z3Interface.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 522928f047d0..fbbd7a58db06 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -72,28 +72,21 @@ void Z3Interface::addAssertion(Expression const& _expr) pair> Z3Interface::check(vector const& _expressionsToEvaluate) { -// cout << "---------------------------------" << endl; -// cout << m_solver << endl; CheckResult result; switch (m_solver.check()) { case z3::check_result::sat: result = CheckResult::SATISFIABLE; - cout << "sat" << endl; break; case z3::check_result::unsat: result = CheckResult::UNSATISFIABLE; - cout << "unsat" << endl; break; case z3::check_result::unknown: result = CheckResult::UNKNOWN; - cout << "unknown" << endl; break; default: solAssert(false, ""); } -// cout << "---------------------------------" << endl; - vector values; if (result != CheckResult::UNSATISFIABLE) From a1f304664735078c5b3d11e1d9d0334dffdf6bbd Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 10:28:41 +0200 Subject: [PATCH 036/108] Add SMT tests. --- docs/contributing.rst | 6 ++++-- test/TestHelper.cpp | 2 ++ test/TestHelper.h | 1 + test/boostTest.cpp | 19 ++++++++++++++----- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 01caa5b15129..0f7c3e7266da 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -64,9 +64,11 @@ Running the compiler tests ========================== Solidity includes different types of tests. They are included in the application -called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode. +called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode, +some others require ``libz3`` to be installed. -To run a subset of the tests that do not require ``cpp-ethereum``, use ``./build/test/soltest -- --no-ipc``. +To disable the z3 tests, use ``./build/test/soltest -- --no-smt`` and +to run a subset of the tests that do not require ``cpp-ethereum``, use ``./build/test/soltest -- --no-ipc``. For all other tests, you need to install `cpp-ethereum `_ and run it in testing mode: ``eth --test -d /tmp/testeth``. diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 094b59c60cd1..c8747a06a42c 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -45,6 +45,8 @@ Options::Options() showMessages = true; else if (string(suite.argv[i]) == "--no-ipc") disableIPC = true; + else if (string(suite.argv[i]) == "--no-smt") + disableSMT = true; if (!disableIPC && ipcPath.empty()) if (auto path = getenv("ETH_TEST_IPC")) diff --git a/test/TestHelper.h b/test/TestHelper.h index d50568ad9e59..d25c5cd819eb 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -35,6 +35,7 @@ struct Options: boost::noncopyable bool showMessages = false; bool optimize = false; bool disableIPC = false; + bool disableSMT = false; static Options const& get(); diff --git a/test/boostTest.cpp b/test/boostTest.cpp index d8c5b678a5c1..7b452e061382 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -39,6 +39,17 @@ using namespace boost::unit_test; +namespace +{ +void removeTestSuite(std::string const& _name) +{ + master_test_suite_t& master = framework::master_test_suite(); + auto id = master.get(_name); + assert(id != INV_TEST_UNIT_ID); + master.remove(id); +} +} + test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) { master_test_suite_t& master = framework::master_test_suite(); @@ -57,12 +68,10 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityEndToEndTest", "SolidityOptimizer" }) - { - auto id = master.get(suite); - assert(id != INV_TEST_UNIT_ID); - master.remove(id); - } + removeTestSuite(suite); } + if (dev::test::Options::get().disableSMT) + removeTestSuite("SMTChecker"); return 0; } From 5028ccbe84cc0732ce9e84c9f55fa2cf8fd7f666 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 10:59:34 +0200 Subject: [PATCH 037/108] Tests for SMT checker. --- test/libsolidity/SMTChecker.cpp | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 test/libsolidity/SMTChecker.cpp diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp new file mode 100644 index 000000000000..d58f296fd53f --- /dev/null +++ b/test/libsolidity/SMTChecker.cpp @@ -0,0 +1,86 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * Unit tests for the SMT checker. + */ + +#include + +#include + +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerFramework: public AnalysisFramework +{ +public: + SMTCheckerFramework() + { + m_warningsToFilter.push_back("Experimental features are turned on."); + } + +protected: + virtual std::pair> + parseAnalyseAndReturnError( + std::string const& _source, + bool _reportWarnings = false, + bool _insertVersionPragma = true, + bool _allowMultipleErrors = false + ) + { + return AnalysisFramework::parseAnalyseAndReturnError( + "pragma experimental SMTChecker;\n" + _source, + _reportWarnings, + _insertVersionPragma, + _allowMultipleErrors + ); + } +}; + +BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + string text = R"( + contract C { } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(simple_overflow) +{ + string text = R"( + contract C { + function f(uint a, uint b) public pure returns (uint) { return a + b; } + } + )"; + CHECK_WARNING(text, "Overflow (resulting value larger than"); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} From 3be37d15e0ac51ca57fd2749609ed7c6dcdc8b07 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 16:01:10 +0200 Subject: [PATCH 038/108] Install libz3-dev from PPA if the distribution does not provide it. --- .travis.yml | 7 ------- scripts/install_deps.sh | 17 ++++++++--------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index c30e3e0f1764..708d3620e8a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,13 +49,6 @@ env: matrix: include: - # Ubuntu 14.04 LTS "Trusty Tahr" - # https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_14.04_LTS_.28Trusty_Tahr.29 - # - # TravisCI doesn't directly support any new Ubuntu releases. These is - # some Docker support, which we should probably investigate, at least for - # Ubuntu 16.04 LTS "Xenial Xerus" - # See https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_16.04_LTS_.28Xenial_Xerus.29. - os: linux dist: trusty sudo: required diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 3a1abe10004a..01dee81d648a 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -256,15 +256,6 @@ case $(uname -s) in #------------------------------------------------------------------------------ # Ubuntu # -# TODO - I wonder whether all of the Ubuntu-variants need some special -# treatment? -# -# TODO - We should also test this code on Ubuntu Server, Ubuntu Snappy Core -# and Ubuntu Phone. -# -# TODO - Our Ubuntu build is only working for amd64 and i386 processors. -# It would be good to add armel, armhf and arm64. -# See https://github.com/ethereum/webthree-umbrella/issues/228. #------------------------------------------------------------------------------ Ubuntu) @@ -320,6 +311,14 @@ case $(uname -s) in libboost-all-dev \ "$install_z3" if [ "$CI" = true ]; then + # install Z3 from PPA if the distribution does not provide it + if ! dpkg -l libz3-dev > /dev/null 2>&1 + then + sudo apt-add-repository -y ppa:hvr/z3 + sudo apt-get -y update + sudo apt-get -y install libz3-dev + fi + # Install 'eth', for use in the Solidity Tests-over-IPC. # We will not use this 'eth', but its dependencies sudo add-apt-repository -y ppa:ethereum/ethereum From 5cded778210c5b1c4278fe71aa676b6f1647acc5 Mon Sep 17 00:00:00 2001 From: Ilya Drabenia Date: Fri, 29 Sep 2017 18:03:40 +0300 Subject: [PATCH 039/108] Add solhint to list of tools. Hello! I develop linter that provide both security, style guide and best practices validations for Solidity users. I will be glad if it will be useful for this community! --- docs/index.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index cb093bd6bbe4..b1d778903112 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,6 +61,9 @@ Available Solidity Integrations * `Solium `_ A commandline linter for Solidity which strictly follows the rules prescribed by the `Solidity Style Guide `_. + +* `Solhint `_ + Solidity linter that provides security, style guide and best practice rules for smart contract validation. * `Visual Studio Code extension `_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. From b1741b7735fea0f0ee8169bf8e48057bbdaf489d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 18 Sep 2017 11:09:20 +0100 Subject: [PATCH 040/108] Validate array length in type checker --- Changelog.md | 1 + libsolidity/analysis/ReferencesResolver.cpp | 2 +- test/libsolidity/SolidityNameAndTypeResolution.cpp | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index a83c6ddb184e..cbcf83ca4e8b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Features: Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. + * Type Checker: Properly check array length and don't rely on an assertion in code generation. * Type Checker: Properly support overwriting members inherited from ``address`` in a contract (such as ``balance``, ``transfer``, etc.) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 8f07d43a572d..a7fa908dbd89 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -149,7 +149,7 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) if (!length->annotation().type) ConstantEvaluator e(*length); auto const* lengthType = dynamic_cast(length->annotation().type.get()); - if (!lengthType || lengthType->isFractional()) + if (!lengthType || lengthType->isFractional() || !lengthType->mobileType()) fatalTypeError(length->location(), "Invalid array length, expected integer literal."); else if (lengthType->isNegative()) fatalTypeError(length->location(), "Array with negative length specified."); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 959bc4ffc8a2..91c2adb198d5 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6976,6 +6976,16 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(array_length_validation) +{ + char const* text = R"( + contract C { + uint[8**90] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); +} + BOOST_AUTO_TEST_SUITE_END() } From e434437eb71e03483232a55aac8c53928fe63d38 Mon Sep 17 00:00:00 2001 From: Rhett Aultman Date: Wed, 20 Sep 2017 11:52:10 -0400 Subject: [PATCH 041/108] Unary + now a synax error (experimental 0.5.0) The unary + was deprecated with a warning, but will be elevated to an error in 0.5.0. This adds the syntax error for the 0.5.0 pragma, and for a true 0.5.0 release we should consider removing the operator from the parser. --- Changelog.md | 1 + libsolidity/analysis/SyntaxChecker.cpp | 9 ++++++- .../SolidityNameAndTypeResolution.cpp | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index cbcf83ca4e8b..008b3c868f8a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Features: * Parser: Better error message for unexpected trailing comma in parameter lists. + * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 187eb26fabb3..0ca4b86c6e63 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -182,8 +182,15 @@ bool SyntaxChecker::visit(Throw const& _throwStatement) bool SyntaxChecker::visit(UnaryOperation const& _operation) { + bool const v050 = m_sourceUnit->annotation().experimentalFeatures.count(ExperimentalFeature::V050); + if (_operation.getOperator() == Token::Add) - m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated."); + { + if (v050) + m_errorReporter.syntaxError(_operation.location(), "Use of unary + is deprecated."); + else + m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated."); + } return true; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 91c2adb198d5..c3a1ce087eea 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4135,6 +4135,8 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; CHECK_SUCCESS_NO_WARNINGS(text); + + // Test deprecation warning under < 0.5.0 text = R"( contract test { function f() pure public { @@ -4154,6 +4156,29 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; CHECK_WARNING(text,"Use of unary + is deprecated"); + + // Test syntax error under 0.5.0 + text = R"( + pragma experimental "v0.5.0"; + contract test { + function f() pure public { + ufixed16x2 a = +3.25; + fixed16x2 b = -3.25; + a; b; + } + } + )"; + CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); + text = R"( + pragma experimental "v0.5.0"; + contract test { + function f(uint x) pure public { + uint y = +x; + y; + } + } + )"; + CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); } BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) From 6d9544795543498e9bc92943c41f07c2daf3bb78 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Fri, 29 Sep 2017 18:45:17 -0300 Subject: [PATCH 042/108] Emit error when declaring event with same name and arguments twice --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 44 +++++++++++++++ libsolidity/analysis/TypeChecker.h | 1 + .../SolidityNameAndTypeResolution.cpp | 55 +++++++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/Changelog.md b/Changelog.md index 008b3c868f8a..81f0b3a6fcdb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Bugfixes: * Type Checker: Properly check array length and don't rely on an assertion in code generation. * Type Checker: Properly support overwriting members inherited from ``address`` in a contract (such as ``balance``, ``transfer``, etc.) + * Type Checker: Prevent duplicate event declarations. ### 0.4.17 (2017-09-21) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4393012522a8..601547581fdc 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -75,6 +75,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); checkContractDuplicateFunctions(_contract); + checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); checkContractAbstractFunctions(_contract); checkContractAbstractConstructors(_contract); @@ -218,6 +219,49 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con } } +void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) +{ + /// Checks that two events with the same name defined in this contract have different + /// argument types + map> events; + for (EventDefinition const* event: _contract.events()) + events[event->name()].push_back(event); + + for (auto const& it: events) + { + vector const& overloads = it.second; + set reported; + for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) + { + SecondarySourceLocation ssl; + + for (size_t j = i + 1; j < overloads.size(); ++j) + if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j]))) + { + ssl.append("Other declaration is here:", overloads[j]->location()); + reported.insert(j); + } + + if (ssl.infos.size() > 0) + { + string msg = "Event with same name and arguments defined twice."; + size_t occurrences = ssl.infos.size(); + if (occurrences > 32) + { + ssl.infos.resize(32); + msg += " Truncated from " + boost::lexical_cast(occurrences) + " to the first 32 occurrences."; + } + + m_errorReporter.declarationError( + overloads[i]->location(), + ssl, + msg + ); + } + } + } +} + void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) { // Mapping from name to function definition (exactly one per argument type equality class) and diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 0c6f54d3f1e0..929be6e6e3ea 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -61,6 +61,7 @@ class TypeChecker: private ASTConstVisitor /// Checks that two functions defined in this contract with the same name have different /// arguments and that there is at most one constructor. void checkContractDuplicateFunctions(ContractDefinition const& _contract); + void checkContractDuplicateEvents(ContractDefinition const& _contract); void checkContractIllegalOverrides(ContractDefinition const& _contract); /// Reports a type error with an appropiate message if overriden function signature differs. /// Also stores the direct super function in the AST annotations. diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index c3a1ce087eea..8b1122579194 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1395,6 +1395,61 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) BOOST_CHECK(success(text)); } +BOOST_AUTO_TEST_CASE(events_with_same_name_unnamed_arguments) +{ + char const* text = R"( + contract test { + event A(uint); + event A(uint, uint); + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(events_with_same_name_different_types) +{ + char const* text = R"( + contract test { + event A(uint); + event A(bytes); + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint i); + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_anonymous) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint i) anonymous; + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_indexed) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint indexed i); + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + BOOST_AUTO_TEST_CASE(event_call) { char const* text = R"( From 1e7b6875b7c5ddc9d257bac65e17d25b8f26fdd2 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Fri, 29 Sep 2017 19:45:56 -0300 Subject: [PATCH 043/108] Extract duplicate function or event finding logic --- libsolidity/analysis/TypeChecker.cpp | 48 +++++++--------------------- libsolidity/analysis/TypeChecker.h | 3 ++ 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 601547581fdc..d45e9e8997da 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -184,39 +184,8 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con msg ); } - for (auto const& it: functions) - { - vector const& overloads = it.second; - set reported; - for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) - { - SecondarySourceLocation ssl; - - for (size_t j = i + 1; j < overloads.size(); ++j) - if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j]))) - { - ssl.append("Other declaration is here:", overloads[j]->location()); - reported.insert(j); - } - if (ssl.infos.size() > 0) - { - string msg = "Function with same name and arguments defined twice."; - size_t occurrences = ssl.infos.size(); - if (occurrences > 32) - { - ssl.infos.resize(32); - msg += " Truncated from " + boost::lexical_cast(occurrences) + " to the first 32 occurrences."; - } - - m_errorReporter.declarationError( - overloads[i]->location(), - ssl, - msg - ); - } - } - } + findDuplicateDefinitions(functions, "Function with same name and arguments defined twice."); } void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) @@ -227,9 +196,15 @@ void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contra for (EventDefinition const* event: _contract.events()) events[event->name()].push_back(event); - for (auto const& it: events) + findDuplicateDefinitions(events, "Event with same name and arguments defined twice."); +} + +template +void TypeChecker::findDuplicateDefinitions(map> const& _definitions, string _message) +{ + for (auto const& it: _definitions) { - vector const& overloads = it.second; + vector const& overloads = it.second; set reported; for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) { @@ -244,18 +219,17 @@ void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contra if (ssl.infos.size() > 0) { - string msg = "Event with same name and arguments defined twice."; size_t occurrences = ssl.infos.size(); if (occurrences > 32) { ssl.infos.resize(32); - msg += " Truncated from " + boost::lexical_cast(occurrences) + " to the first 32 occurrences."; + _message += " Truncated from " + boost::lexical_cast(occurrences) + " to the first 32 occurrences."; } m_errorReporter.declarationError( overloads[i]->location(), ssl, - msg + _message ); } } diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 929be6e6e3ea..abe6dac1e96c 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -109,6 +109,9 @@ class TypeChecker: private ASTConstVisitor virtual void endVisit(ElementaryTypeNameExpression const& _expr) override; virtual void endVisit(Literal const& _literal) override; + template + void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); + bool contractDependenciesAreCyclic( ContractDefinition const& _contract, std::set const& _seenContracts = std::set() From 8a32d7c3d73a303198ab069459718cd2de1be67c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 10:22:58 +0100 Subject: [PATCH 044/108] Add helpers for isPush/isDup/isSwap --- libevmasm/Instruction.h | 18 ++++++++++++++++++ libsolidity/inlineasm/AsmParser.cpp | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index afbef71d0a32..d9c53900b603 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -197,6 +197,24 @@ enum class Instruction: uint8_t SELFDESTRUCT = 0xff ///< halt execution and register account for later deletion }; +/// @returns true if the instruction is a PUSH +inline bool isPushInstruction(Instruction _inst) +{ + return Instruction::PUSH1 <= _inst && _inst <= Instruction::PUSH32; +} + +/// @returns true if the instruction is a DUP +inline bool isDupInstruction(Instruction _inst) +{ + return Instruction::DUP1 <= _inst && _inst <= Instruction::DUP16; +} + +/// @returns true if the instruction is a SWAP +inline bool isSwapInstruction(Instruction _inst) +{ + return Instruction::SWAP1 <= _inst && _inst <= Instruction::SWAP16; +} + /// @returns the number of PUSH Instruction _inst inline unsigned getPushNumber(Instruction _inst) { diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 3087ad864813..1f4df75b0cc3 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -256,7 +256,7 @@ std::map const& Parser::instructions() { if ( instruction.second == solidity::Instruction::JUMPDEST || - (solidity::Instruction::PUSH1 <= instruction.second && instruction.second <= solidity::Instruction::PUSH32) + solidity::isPushInstruction(instruction.second) ) continue; string name = instruction.first; @@ -443,9 +443,9 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction) ret.location = ret.instruction.location; solidity::Instruction instr = ret.instruction.instruction; InstructionInfo instrInfo = instructionInfo(instr); - if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16) + if (solidity::isDupInstruction(instr)) fatalParserError("DUPi instructions not allowed for functional notation"); - if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16) + if (solidity::isSwapInstruction(instr)) fatalParserError("SWAPi instructions not allowed for functional notation"); expectToken(Token::LParen); unsigned args = unsigned(instrInfo.args); From 71aca8c86d3721bcbf21f1f1649f07cf732f2090 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 11:41:47 +0100 Subject: [PATCH 045/108] Always return a valid pointer in Exception::what() --- libdevcore/Exceptions.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libdevcore/Exceptions.cpp b/libdevcore/Exceptions.cpp index f422d926574d..25fd147872ed 100644 --- a/libdevcore/Exceptions.cpp +++ b/libdevcore/Exceptions.cpp @@ -27,7 +27,9 @@ char const* Exception::what() const noexcept if (string const* cmt = comment()) return cmt->c_str(); else - return nullptr; + /// Boost accepts nullptr, but the C++ standard doesn't + /// and crashes on some platforms. + return std::exception::what(); } string Exception::lineInfo() const From cddfec27eef40c1bbf16e8d5881030b85e1082c8 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 11:48:26 +0100 Subject: [PATCH 046/108] lll: better error reporting in some cases --- liblll/CodeFragment.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 254f436fba0f..5e60f96455f5 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -103,7 +103,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS { bigint i = *_t.get(); if (i < 0 || i > bigint(u256(0) - 1)) - error(); + error(toString(i)); m_asm.append((u256)i); break; } @@ -157,7 +157,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { auto i = *++_t.begin(); if (i.tag()) - error(); + error(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get, sp::utree_type::string_type>>(); @@ -244,7 +244,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (ii == 1) { if (i.tag()) - error(); + error(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get, sp::utree_type::string_type>>(); @@ -303,11 +303,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { pos = CodeFragment(i, _s); if (pos.m_asm.deposit() != 1) - error(us); + error(toString(i)); } else if (i.tag() != 0) { - error(); + error(toString(i)); } else if (i.which() == sp::utree_type::string_type) { @@ -318,7 +318,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { bigint bi = *i.get(); if (bi < 0) - error(); + error(toString(i)); else { bytes tmp = toCompactBigEndian(bi); @@ -327,7 +327,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else { - error(); + error(toString(i)); } ii++; From 326c7887a42a04b9e27e8ddb4d8c8d0715d814e1 Mon Sep 17 00:00:00 2001 From: benjaminion Date: Sat, 22 Jul 2017 07:57:38 +0100 Subject: [PATCH 047/108] LLL: Implement a switch expression. --- liblll/CodeFragment.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 254f436fba0f..a7cb3699037b 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -514,6 +514,44 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.appendJump(begin); m_asm << end.tag(); } + else if (us == "SWITCH") + { + requireMinSize(1); + + bool hasDefault = (code.size() % 2 == 1); + int startDeposit = m_asm.deposit(); + int targetDeposit = hasDefault ? code[code.size() - 1].m_asm.deposit() : 0; + + // The conditions + AssemblyItems jumpTags; + for (unsigned i = 0; i < code.size() - 1; i += 2) + { + requireDeposit(i, 1); + m_asm.append(code[i].m_asm); + jumpTags.push_back(m_asm.appendJumpI()); + } + + // The default, if present + if (hasDefault) + m_asm.append(code[code.size() - 1].m_asm); + + // The targets - appending in reverse makes the top case the most efficient. + if (code.size() > 1) + { + auto end = m_asm.appendJump(); + for (int i = 2 * (code.size() / 2 - 1); i >= 0; i -= 2) + { + m_asm << jumpTags[i / 2].tag(); + requireDeposit(i + 1, targetDeposit); + m_asm.append(code[i + 1].m_asm); + if (i != 0) + m_asm.appendJump(end); + } + m_asm << end.tag(); + } + + m_asm.setDeposit(startDeposit + targetDeposit); + } else if (us == "ALLOC") { requireSize(1); From cafc0885c45d4681cf87984e297bf3c241ee491a Mon Sep 17 00:00:00 2001 From: benjaminion Date: Sat, 22 Jul 2017 17:20:13 +0100 Subject: [PATCH 048/108] LLL: Tests for the proposed switch expression. --- test/liblll/EndToEndTest.cpp | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 9292d963226c..1a5bb4906260 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -215,6 +215,92 @@ BOOST_AUTO_TEST_CASE(conditional_nested_then) BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); } +BOOST_AUTO_TEST_CASE(conditional_switch) +{ + char const* sourceCode = R"( + (returnlll + (seq + (def 'input (calldataload 0x04)) + ;; Calculates width in bytes of utf-8 characters. + (return + (switch + (< input 0x80) 1 + (< input 0xE0) 2 + (< input 0xF0) 3 + (< input 0xF8) 4 + (< input 0xFC) 5 + 6)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); + BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); + BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); + BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); + BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_two_args) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch (= (calldataload 0x04) 1) [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch (= (calldataload 0x04) 1) 41 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (switch + (= (calldataload 0x04) 1) (return 41) + (return 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( From d010d6300c667bbe81469a23e6bf76015623e76b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 12:40:52 +0100 Subject: [PATCH 049/108] LLL: Add compiler tests --- test/liblll/Compiler.cpp | 128 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 test/liblll/Compiler.cpp diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp new file mode 100644 index 000000000000..2d66bce1fe4f --- /dev/null +++ b/test/liblll/Compiler.cpp @@ -0,0 +1,128 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Alex Beregszaszi + * @date 2017 + * Unit tests for the LLL compiler. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace lll +{ +namespace test +{ + +namespace +{ + +bool successCompile(std::string const& _sourceCode) +{ + std::vector errors; + bytes bytecode = eth::compileLLL(_sourceCode, false, &errors); + if (!errors.empty()) + return false; + if (bytecode.empty()) + return false; + return true; +} + +} + +BOOST_AUTO_TEST_SUITE(LLLCompiler) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* sourceCode = "1"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_valid) +{ + char const* sourceCode = R"( + (switch (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_invalid_arg_count) +{ + char const* sourceCode = R"( + (switch) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) +{ + // cannot return stack items if the default case is not present + char const* sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (panic)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (origin)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces From 931c0bcce35b05cbe54c0eacb23669e76e1b4a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 2 Oct 2017 16:49:45 +0200 Subject: [PATCH 050/108] Refactor Exception::what() --- libdevcore/Exceptions.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libdevcore/Exceptions.cpp b/libdevcore/Exceptions.cpp index 25fd147872ed..f204dbc2e530 100644 --- a/libdevcore/Exceptions.cpp +++ b/libdevcore/Exceptions.cpp @@ -24,12 +24,14 @@ using namespace dev; char const* Exception::what() const noexcept { + // Return the comment if available. if (string const* cmt = comment()) - return cmt->c_str(); - else - /// Boost accepts nullptr, but the C++ standard doesn't - /// and crashes on some platforms. - return std::exception::what(); + return cmt->data(); + + // Fallback to base what(). + // Boost accepts nullptr, but the C++ standard doesn't + // and crashes on some platforms. + return std::exception::what(); } string Exception::lineInfo() const From cbd4465a7f0337450316bd38fb8613542fc134b9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 10:25:06 +0100 Subject: [PATCH 051/108] lll: do not expose push/dup/swap/jumpdest as functions --- liblll/CodeFragment.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 4fa2c646aded..6951c40acc72 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -113,6 +113,22 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS } } +namespace +{ +/// Returns true iff the instruction is valid as a function. +bool validFunctionalInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) || + solidity::isDupInstruction(it->second) || + solidity::isSwapInstruction(it->second) || + it->second == solidity::Instruction::JUMPDEST + ); +} +} + void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { if (_t.tag() == 0 && _t.empty()) @@ -409,7 +425,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) for (auto const& i: cs.macros) _s.macros.insert(i); } - else if (c_instructions.count(us)) + else if (c_instructions.count(us) && validFunctionalInstruction(us)) { auto it = c_instructions.find(us); requireSize(instructionInfo(it->second).args); From 26f3ea8cf7fba8d8222ab1889cfbf89046371d10 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 2 Oct 2017 13:17:52 +0100 Subject: [PATCH 052/108] LLL: change (include) to use a callback --- liblll/CodeFragment.cpp | 25 +++++++++++++------------ liblll/CodeFragment.h | 7 +++++-- liblll/Compiler.cpp | 9 +++++---- liblll/Compiler.h | 6 ++++-- liblll/CompilerState.cpp | 2 +- lllc/main.cpp | 4 ++-- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 6951c40acc72..49c4802777e9 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -47,7 +47,8 @@ void CodeFragment::finalise(CompilerState const& _cs) } } -CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM) +CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM): + m_readFile(_readFile) { /* std::cout << "CodeFragment. Locals:"; @@ -214,7 +215,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) int c = 0; for (auto const& i: _t) if (c++) - m_asm.append(CodeFragment(i, _s, true).m_asm); + m_asm.append(CodeFragment(i, _s, m_readFile, true).m_asm); } else if (us == "INCLUDE") { @@ -223,10 +224,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) string fileName = firstAsString(); if (fileName.empty()) error("Empty file name provided"); - string contents = contentsString(fileName); + string contents = m_readFile(fileName); if (contents.empty()) error(std::string("File not found (or empty): ") + fileName); - m_asm.append(CodeFragment::compile(contents, _s).m_asm); + m_asm.append(CodeFragment::compile(contents, _s, m_readFile).m_asm); } else if (us == "SET") { @@ -235,7 +236,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) int c = 0; for (auto const& i: _t) if (c++ == 2) - m_asm.append(CodeFragment(i, _s, false).m_asm); + m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); m_asm.append((u256)varAddress(firstAsString(), true)); m_asm.append(Instruction::MSTORE); } @@ -276,7 +277,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (_t.size() == 3) { /// NOTE: some compilers could do the assignment first if this is done in a single line - CodeFragment code = CodeFragment(i, _s); + CodeFragment code = CodeFragment(i, _s, m_readFile); _s.defs[n] = code; } else @@ -317,7 +318,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else if (ii == 1) { - pos = CodeFragment(i, _s); + pos = CodeFragment(i, _s, m_readFile); if (pos.m_asm.deposit() != 1) error(toString(i)); } @@ -396,9 +397,9 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (c++) { if (us == "LLL" && c == 1) - code.push_back(CodeFragment(i, ns)); + code.push_back(CodeFragment(i, ns, m_readFile)); else - code.push_back(CodeFragment(i, _s)); + code.push_back(CodeFragment(i, _s, m_readFile)); } auto requireSize = [&](unsigned s) { if (code.size() != s) error(us); }; auto requireMinSize = [&](unsigned s) { if (code.size() < s) error(us); }; @@ -419,7 +420,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) //requireDeposit(i, 1); cs.args[m.args[i]] = code[i]; } - m_asm.append(CodeFragment(m.code, cs).m_asm); + m_asm.append(CodeFragment(m.code, cs, m_readFile).m_asm); for (auto const& i: cs.defs) _s.defs[i.first] = i.second; for (auto const& i: cs.macros) @@ -676,13 +677,13 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } } -CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s) +CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s, ReadCallback const& _readFile) { CodeFragment ret; sp::utree o; parseTreeLLL(_src, o); if (!o.empty()) - ret = CodeFragment(o, _s); + ret = CodeFragment(o, _s, _readFile); _s.treesToKill.push_back(o); return ret; } diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index 95d21563fe6e..e5cac34e9d1f 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -39,10 +39,12 @@ struct CompilerState; class CodeFragment { public: + using ReadCallback = std::function; + CodeFragment() {} - CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM = false); + CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM = false); - static CodeFragment compile(std::string const& _src, CompilerState& _s); + static CodeFragment compile(std::string const& _src, CompilerState& _s, ReadCallback const& _readFile); /// Consolidates data and compiles code. Assembly& assembly(CompilerState const& _cs) { finalise(_cs); return m_asm; } @@ -60,6 +62,7 @@ class CodeFragment bool m_finalised = false; Assembly m_asm; + ReadCallback m_readFile; }; static const CodeFragment NullCodeFragment; diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index b69675aabe60..1638f69e3388 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -28,13 +28,14 @@ using namespace std; using namespace dev; using namespace dev::eth; -bytes dev::eth::compileLLL(string const& _src, bool _opt, vector* _errors) + +bytes dev::eth::compileLLL(string const& _src, bool _opt, vector* _errors, ReadCallback const& _readFile) { try { CompilerState cs; cs.populateStandard(); - auto assembly = CodeFragment::compile(_src, cs).assembly(cs); + auto assembly = CodeFragment::compile(_src, cs, _readFile).assembly(cs); if (_opt) assembly = assembly.optimise(true); bytes ret = assembly.assemble().bytecode; @@ -66,13 +67,13 @@ bytes dev::eth::compileLLL(string const& _src, bool _opt, vector* _error return bytes(); } -std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector* _errors) +std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector* _errors, ReadCallback const& _readFile) { try { CompilerState cs; cs.populateStandard(); - auto assembly = CodeFragment::compile(_src, cs).assembly(cs); + auto assembly = CodeFragment::compile(_src, cs, _readFile).assembly(cs); if (_opt) assembly = assembly.optimise(true); string ret = assembly.assemblyString(); diff --git a/liblll/Compiler.h b/liblll/Compiler.h index 04aa1e268e84..c3395b667c4b 100644 --- a/liblll/Compiler.h +++ b/liblll/Compiler.h @@ -30,9 +30,11 @@ namespace dev namespace eth { +using ReadCallback = std::function; + std::string parseLLL(std::string const& _src); -std::string compileLLLToAsm(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr); -bytes compileLLL(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr); +std::string compileLLLToAsm(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); +bytes compileLLL(std::string const& _src, bool _opt = true, std::vector* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); } } diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp index d53dec7e5c2d..c0e344b2a09d 100644 --- a/liblll/CompilerState.cpp +++ b/liblll/CompilerState.cpp @@ -82,5 +82,5 @@ void CompilerState::populateStandard() "(def 'shl (val shift) (mul val (exp 2 shift)))" "(def 'shr (val shift) (div val (exp 2 shift)))" "}"; - CodeFragment::compile(s, *this); + CodeFragment::compile(s, *this, CodeFragment::ReadCallback()); } diff --git a/lllc/main.cpp b/lllc/main.cpp index 06a0fc81b784..912ce16af4d5 100644 --- a/lllc/main.cpp +++ b/lllc/main.cpp @@ -138,7 +138,7 @@ int main(int argc, char** argv) } else if (mode == Binary || mode == Hex) { - auto bs = compileLLL(src, optimise ? true : false, &errors); + auto bs = compileLLL(src, optimise ? true : false, &errors, contentsString); if (mode == Hex) cout << toHex(bs) << endl; else if (mode == Binary) @@ -147,7 +147,7 @@ int main(int argc, char** argv) else if (mode == ParseTree) cout << parseLLL(src) << endl; else if (mode == Assembly) - cout << compileLLLToAsm(src, optimise ? true : false, &errors) << endl; + cout << compileLLLToAsm(src, optimise ? true : false, &errors, contentsString) << endl; for (auto const& i: errors) cerr << i << endl; if ( errors.size() ) From ab206b8113c8127f8750e1fb1a541bf20950f225 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 3 Oct 2017 10:22:30 +0100 Subject: [PATCH 053/108] LLL: do not crash if import callback is null --- liblll/CodeFragment.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 49c4802777e9..d4ef38883dc2 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -224,6 +224,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) string fileName = firstAsString(); if (fileName.empty()) error("Empty file name provided"); + if (!m_readFile) + error("Import callback not present"); string contents = m_readFile(fileName); if (contents.empty()) error(std::string("File not found (or empty): ") + fileName); From fe947006ffb59f424811be47053754190933c170 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 13 Sep 2017 11:34:40 +0100 Subject: [PATCH 054/108] Format chainparams fields properly in tests --- test/RPCSession.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index c4fbfefb6baa..768c8c4bbd8f 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -217,11 +217,11 @@ void RPCSession::test_setChainParams(vector const& _accounts) { "sealEngine": "NoProof", "params": { - "accountStartNonce": "0x", + "accountStartNonce": "0x00", "maximumExtraDataSize": "0x1000000", "blockReward": "0x", - "allowFutureBlocks": "1", - "homsteadForkBlock": "0x00", + "allowFutureBlocks": true, + "homesteadForkBlock": "0x00", "EIP150ForkBlock": "0x00", "EIP158ForkBlock": "0x00" }, From e952946b229c626d677aed00d8dcb552292f674c Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 26 Sep 2017 17:15:48 +0200 Subject: [PATCH 055/108] Use byzantium version of eth. --- scripts/tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tests.sh b/scripts/tests.sh index 5d7eb0e1faf7..bf3e34550ea1 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -42,8 +42,8 @@ elif [ -z $CI ]; then ETH_PATH="eth" else mkdir -p /tmp/test - wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth - test "$(shasum /tmp/test/eth)" = "c132e8989229e4840831a4fb1a1d058b732a11d5 /tmp/test/eth" + wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium + test "$(shasum /tmp/test/eth)" = "6e16ae5e0a0079d85fd63fb43547be3c52410e7e /tmp/test/eth" sync chmod +x /tmp/test/eth sync # Otherwise we might get a "text file busy" error From 43719839bf02a17cea2014266abca837f88ab35e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 3 Oct 2017 11:45:44 +0100 Subject: [PATCH 056/108] Use isDup/SwapInstruction helper --- libevmasm/AssemblyItem.cpp | 4 +--- libevmasm/SemanticInformation.cpp | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index cfe91be09bbc..649630217bda 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -17,8 +17,6 @@ #include -#include - #include #include @@ -112,7 +110,7 @@ bool AssemblyItem::canBeFunctional() const switch (m_type) { case Operation: - return !SemanticInformation::isDupInstruction(*this) && !SemanticInformation::isSwapInstruction(*this); + return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); case Push: case PushString: case PushTag: diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index ceb3fbdd0cce..83cfe2c6d4cd 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -90,14 +90,14 @@ bool SemanticInformation::isDupInstruction(AssemblyItem const& _item) { if (_item.type() != Operation) return false; - return Instruction::DUP1 <= _item.instruction() && _item.instruction() <= Instruction::DUP16; + return solidity::isDupInstruction(_item.instruction()); } bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) { if (_item.type() != Operation) return false; - return Instruction::SWAP1 <= _item.instruction() && _item.instruction() <= Instruction::SWAP16; + return solidity::isSwapInstruction(_item.instruction()); } bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) From 4d1c48eeee8a0b71b79ce51a811e8f1f3e2388d6 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 3 Oct 2017 11:48:47 +0100 Subject: [PATCH 057/108] Remove duplicate EVMSchedule --- libevmasm/EVMSchedule.h | 62 ----------------------------------- test/libsolidity/GasMeter.cpp | 10 ++---- 2 files changed, 3 insertions(+), 69 deletions(-) delete mode 100644 libevmasm/EVMSchedule.h diff --git a/libevmasm/EVMSchedule.h b/libevmasm/EVMSchedule.h deleted file mode 100644 index 1695a59c2c63..000000000000 --- a/libevmasm/EVMSchedule.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file EVMSchedule.h - * @author Gav - * @author Christian - * @date 2015 - */ - -#pragma once - -namespace dev -{ -namespace solidity -{ - -struct EVMSchedule -{ - unsigned stackLimit = 1024; - unsigned expGas = 10; - unsigned expByteGas = 10; - unsigned keccak256Gas = 30; - unsigned keccak256WordGas = 6; - unsigned sloadGas = 200; - unsigned sstoreSetGas = 20000; - unsigned sstoreResetGas = 5000; - unsigned sstoreRefundGas = 15000; - unsigned jumpdestGas = 1; - unsigned logGas = 375; - unsigned logDataGas = 8; - unsigned logTopicGas = 375; - unsigned createGas = 32000; - unsigned callGas = 40; - unsigned callStipend = 2300; - unsigned callValueTransferGas = 9000; - unsigned callNewAccountGas = 25000; - unsigned selfdestructRefundGas = 24000; - unsigned memoryGas = 3; - unsigned quadCoeffDiv = 512; - unsigned createDataGas = 200; - unsigned txGas = 21000; - unsigned txCreateGas = 53000; - unsigned txDataZeroGas = 4; - unsigned txDataNonZeroGas = 68; - unsigned copyGas = 3; -}; - -} -} diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index b759678fe1b6..c2886f5b4901 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -21,7 +21,6 @@ */ #include -#include #include #include #include @@ -63,15 +62,13 @@ class GasMeterTestFramework: public SolidityExecutionFramework void testCreationTimeGas(string const& _sourceCode) { - EVMSchedule schedule; - compileAndRun(_sourceCode); auto state = make_shared(); PathGasMeter meter(*m_compiler.assemblyItems()); GasMeter::GasConsumption gas = meter.estimateMax(0, state); u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size()); // costs for deployment - gas += bytecodeSize * schedule.createDataGas; + gas += bytecodeSize * GasCosts::createDataGas; // costs for transaction gas += gasForTransaction(m_compiler.object().bytecode, true); @@ -103,10 +100,9 @@ class GasMeterTestFramework: public SolidityExecutionFramework static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation) { - EVMSchedule schedule; - GasMeter::GasConsumption gas = _isCreation ? schedule.txCreateGas : schedule.txGas; + GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas; for (auto i: _data) - gas += i != 0 ? schedule.txDataNonZeroGas : schedule.txDataZeroGas; + gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas; return gas; } From 2b8235269221cacbcf9beb793d969c451b1927a3 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sat, 8 Jul 2017 20:27:28 -0300 Subject: [PATCH 058/108] Disallow non-pure constant state variables in 0.5.0 --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 19 +++++++++--- .../SolidityNameAndTypeResolution.cpp | 31 ++++++++++++++++--- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Changelog.md b/Changelog.md index 81f0b3a6fcdb..8ebc30d051f3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Features: * Parser: Better error message for unexpected trailing comma in parameter lists. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. + * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d45e9e8997da..b2a8805952ec 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -645,14 +645,23 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) if (!allowed) m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented."); } + if (!_variable.value()) m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable."); else if (!_variable.value()->annotation().isPure) - m_errorReporter.warning( - _variable.value()->location(), - "Initial value for constant variable has to be compile-time constant. " - "This will fail to compile with the next breaking version change." - ); + { + if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + m_errorReporter.typeError( + _variable.value()->location(), + "Initial value for constant variable has to be compile-time constant." + ); + else + m_errorReporter.warning( + _variable.value()->location(), + "Initial value for constant variable has to be compile-time constant. " + "This will fail to compile with the next breaking version change." + ); + } } if (!_variable.isStateVariable()) { diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 8b1122579194..c60ccaf894e0 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2361,17 +2361,28 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); } -BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) +BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x) { char const* text = R"( contract C { address constant x = msg.sender; } )"; - // Change to TypeError for 0.5.0. CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); } +BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + + contract C { + address constant x = msg.sender; + } + )"; + CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); +} + BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) { char const* text = R"( @@ -2388,7 +2399,7 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) CHECK_ERROR(text, TypeError, "Index access for string is not possible."); } -BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant_0_4_x) { char const* text = R"( contract C { @@ -2396,10 +2407,22 @@ BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) uint constant y = x(); } )"; - // Change to TypeError for 0.5.0. CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); } +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + + contract C { + function () constant returns (uint) x; + uint constant y = x(); + } + )"; + CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); +} + BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) { char const* text = R"( From 73f17876e9a424f9519e3c4b4364139aaae7a62a Mon Sep 17 00:00:00 2001 From: wadeAlexC Date: Mon, 2 Oct 2017 17:59:39 -0400 Subject: [PATCH 059/108] Better error message when using fractional number as array size expressions --- libsolidity/analysis/ReferencesResolver.cpp | 5 +++-- test/libsolidity/SolidityNameAndTypeResolution.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index a7fa908dbd89..20016112e40d 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -149,8 +149,10 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) if (!length->annotation().type) ConstantEvaluator e(*length); auto const* lengthType = dynamic_cast(length->annotation().type.get()); - if (!lengthType || lengthType->isFractional() || !lengthType->mobileType()) + if (!lengthType || !lengthType->mobileType()) fatalTypeError(length->location(), "Invalid array length, expected integer literal."); + else if (lengthType->isFractional()) + fatalTypeError(length->location(), "Array with fractional length specified."); else if (lengthType->isNegative()) fatalTypeError(length->location(), "Array with negative length specified."); else @@ -347,4 +349,3 @@ void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location, m_errorOccurred = true; m_errorReporter.fatalDeclarationError(_location, _description); } - diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index c60ccaf894e0..ed2236784af3 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4354,7 +4354,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Array with fractional length specified."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) @@ -4366,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) @@ -4378,7 +4378,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) From fefdfc0711e1637df91ef0ec813af0c30ad53af6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 4 Oct 2017 12:48:23 +0200 Subject: [PATCH 060/108] Disable SMT tests on windows. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 3d4d65bb47ec..b50681b96c5b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -71,7 +71,7 @@ build_script: test_script: - cd %APPVEYOR_BUILD_FOLDER% - cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION% - - soltest.exe --show-progress -- --no-ipc + - soltest.exe --show-progress -- --no-ipc --no-smt artifacts: - path: solidity-windows.zip From a5fddc9c57c8d23b3b2c335fa754df9007953039 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 25 Sep 2017 17:00:16 +0200 Subject: [PATCH 061/108] Debugging info in CompilerContext. --- libsolidity/codegen/CompilerContext.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d87c7be5c1ec..ce9c3b7f69e4 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -38,6 +38,13 @@ #include #include +// Change to "define" to output all intermediate code +#undef SOL_OUTPUT_ASM +#ifdef SOL_OUTPUT_ASM +#include +#endif + + using namespace std; namespace dev @@ -313,10 +320,17 @@ void CompilerContext::appendInlineAssembly( ErrorReporter errorReporter(errors); auto scanner = make_shared(CharStream(_assembly), "--CODEGEN--"); auto parserResult = assembly::Parser(errorReporter).parse(scanner); - if (!parserResult || !errorReporter.errors().empty()) +#ifdef SOL_OUTPUT_ASM + cout << assembly::AsmPrinter()(*parserResult) << endl; +#endif + assembly::AsmAnalysisInfo analysisInfo; + bool analyzerResult = false; + if (parserResult) + analyzerResult = assembly::AsmAnalyzer(analysisInfo, errorReporter, false, identifierAccess.resolve).analyze(*parserResult); + if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) { string message = - "Error parsing inline assembly block:\n" + "Error parsing/analyzing inline assembly block:\n" "------------------ Input: -----------------\n" + _assembly + "\n" "------------------ Errors: ----------------\n"; @@ -331,9 +345,6 @@ void CompilerContext::appendInlineAssembly( solAssert(false, message); } - assembly::AsmAnalysisInfo analysisInfo; - assembly::AsmAnalyzer analyzer(analysisInfo, errorReporter, false, identifierAccess.resolve); - solAssert(analyzer.analyze(*parserResult), "Failed to analyze inline assembly block."); solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); assembly::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); } From 364b4dea6269debefc0a7eaedbec4a60fbf0e74d Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 26 Sep 2017 18:25:36 +0200 Subject: [PATCH 062/108] Add some asserts about calldata encoded size. --- libsolidity/codegen/ArrayUtils.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e17188c26e9f..ce8cbb5f2cbc 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -291,8 +291,11 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord CompilerUtils utils(m_context); unsigned baseSize = 1; if (!_sourceType.isByteArray()) + { // We always pad the elements, regardless of _padToWordBoundaries. baseSize = _sourceType.baseType()->calldataEncodedSize(); + solAssert(baseSize >= 0x20, ""); + } if (_sourceType.location() == DataLocation::CallData) { From a9847c955106dbf74d47d68122a634c787e0d00b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 4 Oct 2017 13:05:55 +0100 Subject: [PATCH 063/108] Use solAssert and not assert --- libsolidity/ast/Types.cpp | 2 +- libsolidity/formal/Z3Interface.cpp | 2 +- libsolidity/interface/GasEstimator.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a39b57758d5e..a3cbe50a2af8 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -89,7 +89,7 @@ pair const* StorageOffsets::offset(size_t _index) const MemberList& MemberList::operator=(MemberList&& _other) { - assert(&_other != this); + solAssert(&_other != this, ""); m_memberTypes = move(_other.m_memberTypes); m_storageOffsets = move(_other.m_storageOffsets); diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 522928f047d0..21bad2d69205 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -142,7 +142,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) return m_context.int_val(n.c_str()); } - assert(arity.count(n) && arity.at(n) == arguments.size()); + solAssert(arity.count(n) && arity.at(n) == arguments.size(), ""); if (n == "ite") return z3::ite(arguments[0], arguments[1], arguments[2]); else if (n == "not") diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 852b392c6c86..22cc0266d447 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -48,7 +48,7 @@ GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimatio ControlFlowGraph cfg(_items); for (BasicBlock const& block: cfg.optimisedBlocks()) { - assertThrow(!!block.startState, OptimizerException, ""); + solAssert(!!block.startState, ""); GasMeter meter(block.startState->copy()); auto const end = _items.begin() + block.end; for (auto iter = _items.begin() + block.begin; iter != end; ++iter) From 6de9fc710e6941574b7488af22c8d756590e3f07 Mon Sep 17 00:00:00 2001 From: Dave Hoover Date: Wed, 4 Oct 2017 07:35:05 -0500 Subject: [PATCH 064/108] Minor edits --- docs/common-patterns.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index acef13b72b6f..52319be0d550 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -93,7 +93,7 @@ Notice that, in this example, an attacker could trap the contract into an unusable state by causing ``richest`` to be the address of a contract that has a fallback function which fails (e.g. by using ``revert()`` or by just -conssuming more than the 2300 gas stipend). That way, +consuming more than the 2300 gas stipend). That way, whenever ``transfer`` is called to deliver funds to the "poisoned" contract, it will fail and thus also ``becomeRichest`` will fail, with the contract being stuck forever. @@ -121,7 +121,7 @@ unless you declare make your state variables ``public``. Furthermore, you can restrict who can make modifications to your contract's state or call your contract's -functions and this is what this page is about. +functions and this is what this section is about. .. index:: function;modifier From 80cefb9cc810a96fea5817511d3fd908e960bf80 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 4 Oct 2017 16:56:54 +0200 Subject: [PATCH 065/108] Rename "compacted" to "fromStack". --- libsolidity/codegen/ABIFunctions.cpp | 34 ++++++++++++---------------- libsolidity/codegen/ABIFunctions.h | 6 ++--- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 202a747f18f2..25886844dfa8 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder( ); elementTempl("values", valueNames); elementTempl("pos", to_string(headPos)); - elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false)); + elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true)); encodeElements += elementTempl.render(); headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize(); } @@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction( Type const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solUnimplementedAssert( @@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction( dynamic_cast(_from), to, _encodeAsLibraryTypes, - _compacted + _fromStack ); solAssert(_from.sizeOnStack() == 1, ""); @@ -573,7 +573,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false )); templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" ); templ("nextArrayElement", nextArrayElementFunction(_from)); @@ -716,7 +716,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false ); templ("encodeToMemoryFun", encodeToMemoryFun); std::vector> items(itemsPerSlot); @@ -832,7 +832,7 @@ string ABIFunctions::abiEncodingFunctionStruct( } memberTempl("encodingOffset", toCompactHexWithPrefix(encodingOffset)); encodingOffset += dynamicMember ? 0x20 : memberTypeTo->calldataEncodedSize(); - memberTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, _encodeAsLibraryTypes, true)); + memberTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, _encodeAsLibraryTypes, false)); members.push_back({}); members.back()["encode"] = memberTempl.render(); @@ -909,7 +909,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solAssert(_from.kind() == FunctionType::Kind::External, ""); @@ -920,35 +920,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType( _from.identifier() + "_to_" + _to.identifier() + - (_compacted ? "_compacted" : "") + + (_fromStack ? "_fromStack" : "") + (_encodeAsLibraryTypes ? "_library" : ""); - if (_compacted) - { + if (_fromStack) return createFunction(functionName, [&]() { return Whiskers(R"( - function (addr_and_function_id, pos) { - mstore(pos, (addr_and_function_id)) + function (addr, function_id, pos) { + mstore(pos, (addr, function_id)) } )") ("functionName", functionName) - ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) + ("combineExtFun", combineExternalFunctionIdFunction()) .render(); }); - } else - { return createFunction(functionName, [&]() { return Whiskers(R"( - function (addr, function_id, pos) { - mstore(pos, (addr, function_id)) + function (addr_and_function_id, pos) { + mstore(pos, (addr_and_function_id)) } )") ("functionName", functionName) - ("combineExtFun", combineExternalFunctionIdFunction()) + ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) .render(); }); - } } string ABIFunctions::copyToMemoryFunction(bool _fromCalldata) diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index de2a140ae2c8..e61f68bcc3fc 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -89,13 +89,13 @@ class ABIFunctions /// @returns the name of the ABI encoding function with the given type /// and queues the generation of the function to the requested functions. - /// @param _compacted if true, the input value was just loaded from storage + /// @param _fromStack if false, the input value was just loaded from storage /// or memory and thus might be compacted into a single slot (depending on the type). std::string abiEncodingFunction( Type const& _givenType, Type const& _targetType, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// Part of @a abiEncodingFunction for array target type and given calldata array. std::string abiEncodingFunctionCalldataArray( @@ -143,7 +143,7 @@ class ABIFunctions FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// @returns a function that copies raw bytes of dynamic length from calldata From 76d3d248426994b35c5bc2d92e9ba479cbf44ddc Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Wed, 4 Oct 2017 12:09:52 -0300 Subject: [PATCH 066/108] Do not consider shadowing in variable names inside event declarations --- Changelog.md | 1 + libsolidity/analysis/NameAndTypeResolver.cpp | 6 ++++-- test/libsolidity/SolidityNameAndTypeResolution.cpp | 11 +++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 8ebc30d051f3..ea31095df955 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Bugfixes: * Type Checker: Properly support overwriting members inherited from ``address`` in a contract (such as ``balance``, ``transfer``, etc.) * Type Checker: Prevent duplicate event declarations. + * Type Checker: Do not mark event parameters as shadowing state variables. ### 0.4.17 (2017-09-21) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 523e71769814..5d0106935296 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -647,10 +647,12 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio bool warnAboutShadowing = true; // Do not warn about shadowing for structs and enums because their members are - // not accessible without prefixes. + // not accessible without prefixes. Also do not warn about event parameters + // because they don't participate in any proper scope. if ( dynamic_cast(m_currentScope) || - dynamic_cast(m_currentScope) + dynamic_cast(m_currentScope) || + dynamic_cast(m_currentScope) ) warnAboutShadowing = false; // Do not warn about the constructor shadowing the contract. diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index ed2236784af3..350d41f17292 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6371,6 +6371,17 @@ BOOST_AUTO_TEST_CASE(function_override_is_not_shadowing) CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(event_parameter_cannot_shadow_state_variable) +{ + char const* text = R"( + contract C { + address a; + event E(address a); + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(callable_crash) { char const* text = R"( From f96e932243273050fcf2bd4ba89d80412252a9d9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 13 Sep 2017 19:43:16 +0100 Subject: [PATCH 067/108] Provide optional list of contract names to CompilerStack.compile --- libsolidity/interface/CompilerStack.cpp | 11 ++++++++++- libsolidity/interface/CompilerStack.h | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 51544f8a5b9c..b99fe4ee3992 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -252,6 +252,14 @@ bool CompilerStack::parseAndAnalyze() return parse() && analyze(); } +bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) const +{ + return + m_requestedContractNames.empty() || + m_requestedContractNames.count(_contract.fullyQualifiedName()) || + m_requestedContractNames.count(_contract.name()); +} + bool CompilerStack::compile() { if (m_stackState < AnalysisSuccessful) @@ -262,7 +270,8 @@ bool CompilerStack::compile() for (Source const* source: m_sourceOrder) for (ASTPointer const& node: source->ast->nodes()) if (auto contract = dynamic_cast(node.get())) - compileContract(*contract, compiledContracts); + if (isRequestedContract(*contract)) + compileContract(*contract, compiledContracts); this->link(); m_stackState = CompilationSuccessful; return true; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index f1bbae47e668..c567ac2cb350 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -116,6 +116,13 @@ class CompilerStack: boost::noncopyable m_optimizeRuns = _runs; } + /// Sets the list of requested contract names. If empty, no filtering is performed and every contract + /// found in the supplied sources is compiled. Names are cleared iff @a _contractNames is missing. + void setRequestedContractNames(std::set const& _contractNames = std::set{}) + { + m_requestedContractNames = _contractNames; + } + /// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata. void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; } @@ -259,6 +266,9 @@ class CompilerStack: boost::noncopyable /// Helper function to return path converted strings. std::string sanitizePath(std::string const& _path) const { return boost::filesystem::path(_path).generic_string(); } + /// @returns true if the contract is requested to be compiled. + bool isRequestedContract(ContractDefinition const& _contract) const; + /// Compile a single contract and put the result in @a _compiledContracts. void compileContract( ContractDefinition const& _contract, @@ -297,6 +307,7 @@ class CompilerStack: boost::noncopyable ReadCallback::Callback m_smtQuery; bool m_optimize = false; unsigned m_optimizeRuns = 200; + std::set m_requestedContractNames; std::map m_libraries; /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum /// "context:prefix=target" From a0394a1bfadb93b1f697b43bf52750bbff02af37 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 29 Sep 2017 19:05:39 +0100 Subject: [PATCH 068/108] Restrict contracts compiled via outputSelection (but not the individual output details) --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 19 ++++ test/libsolidity/StandardCompiler.cpp | 116 +++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/Changelog.md b/Changelog.md index 8ebc30d051f3..6f2f40fbcf15 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Features: * Parser: Better error message for unexpected trailing comma in parameter lists. + * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b4fbbef9b12b..430739accc1c 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -92,6 +92,22 @@ Json::Value formatErrorWithException( return formatError(_warning, _type, _component, message, formattedMessage, location); } +set requestedContractNames(Json::Value const& _outputSelection) +{ + set names; + for (auto const& sourceName: _outputSelection.getMemberNames()) + { + for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) + { + /// Consider the "all sources" shortcuts as requesting everything. + if (contractName == "*" || contractName == "") + return set(); + names.insert((sourceName == "*" ? "" : sourceName) + ":" + contractName); + } + } + return names; +} + /// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. bool hashMatchesContent(string const& _hash, string const& _content) { @@ -265,6 +281,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value metadataSettings = settings.get("metadata", Json::Value()); m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool()); + Json::Value outputSelection = settings.get("outputSelection", Json::Value()); + m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection)); + auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compilerStack.scanner(_sourceName); }; try diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 24f915c07aab..03d7f85af4de 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -226,6 +226,122 @@ BOOST_AUTO_TEST_CASE(basic_compilation) ); } +BOOST_AUTO_TEST_CASE(output_selection_explicit) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "fileA": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_contracts) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "fileA": { + "*": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_files_single_contract) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "*": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + BOOST_AUTO_TEST_SUITE_END() } From f86cd06b9755f4827467e86acd4a53603f3da84f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Oct 2017 09:53:43 +0100 Subject: [PATCH 069/108] Add contract depedendency tests to standardcompiler --- test/libsolidity/StandardCompiler.cpp | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 03d7f85af4de..4504946bdcdd 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -342,6 +342,67 @@ BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts) BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); } +BOOST_AUTO_TEST_CASE(output_selection_dependent_contract) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract B { } contract A { function f() { new B(); } }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "import \"fileB\"; contract A { function f() { new B(); } }" + }, + "fileB": { + "content": "contract B { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); +} + BOOST_AUTO_TEST_SUITE_END() } From 69ea5c43f3ef2fe08bed0edbe1d45d4553cbbee4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 5 Oct 2017 11:56:36 +0200 Subject: [PATCH 070/108] Send all gas for 0.5.0. --- Changelog.md | 3 +++ libsolidity/codegen/ExpressionCompiler.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index 8ebc30d051f3..c78a26e0be05 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,9 @@ Features: * Parser: Better error message for unexpected trailing comma in parameter lists. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. + * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature + (previously, some amount was retained in order to work in pre-tangerine whistle + EVM versions) Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c2bf0f5cdf81..fe37baac2741 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1714,6 +1714,9 @@ void ExpressionCompiler::appendExternalFunctionCall( if (_functionType.gasSet()) m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); + else if (m_context.experimentalFeatureActive(ExperimentalFeature::V050)) + // Send all gas (requires tangerine whistle EVM) + m_context << Instruction::GAS; else { // send all gas except the amount needed to execute "SUB" and "CALL" From 10529e994f9a587436c57bfdeef52476da9770bb Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 4 Oct 2017 12:18:40 +0100 Subject: [PATCH 071/108] SMT should not crash on typecast/structs --- libsolidity/formal/SMTChecker.cpp | 10 ++++++++++ test/libsolidity/SMTChecker.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index fd78e578f9ed..7c8c089e338e 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -234,6 +234,16 @@ void SMTChecker::endVisit(BinaryOperation const& _op) void SMTChecker::endVisit(FunctionCall const& _funCall) { + solAssert(_funCall.annotation().kind != FunctionCallKind::Unset, ""); + if (_funCall.annotation().kind != FunctionCallKind::FunctionCall) + { + m_errorReporter.warning( + _funCall.location(), + "Assertion checker does not yet implement this expression." + ); + return; + } + FunctionType const& funType = dynamic_cast(*_funCall.expression().annotation().type); std::vector> const args = _funCall.arguments(); diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index d58f296fd53f..8d712a800b69 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -79,6 +79,32 @@ BOOST_AUTO_TEST_CASE(simple_overflow) CHECK_WARNING(text, "Overflow (resulting value larger than"); } +BOOST_AUTO_TEST_CASE(warn_on_typecast) +{ + string text = R"( + contract C { + function f() public pure returns (uint) { + return uint8(1); + } + } + )"; + CHECK_WARNING(text, "Assertion checker does not yet implement this expression."); +} + +BOOST_AUTO_TEST_CASE(warn_on_struct) +{ + string text = R"( + contract C { + struct A { uint a; uint b; } + function f() public pure returns (A) { + return A({ a: 1, b: 2 }); + } + } + )"; + /// Multiple warnings, should check for: Assertion checker does not yet implement this expression. + CHECK_WARNING_ALLOW_MULTI(text, ""); +} + BOOST_AUTO_TEST_SUITE_END() } From 09276cb9d3589493176bc45b2075517c2087d75b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 Sep 2017 14:11:44 +0100 Subject: [PATCH 072/108] Do not add members of address to contracts in experimental 0.5.0 --- Changelog.md | 7 ++- docs/types.rst | 3 + libsolidity/ast/Types.cpp | 7 ++- .../SolidityNameAndTypeResolution.cpp | 58 +++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 8f97b0e878b0..ace9bc361a4d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,13 +1,14 @@ ### 0.4.18 (unreleased) Features: + * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature + (previously, some amount was retained in order to work in pre-tangerine whistle + EVM versions) * Parser: Better error message for unexpected trailing comma in parameter lists. * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. - * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature - (previously, some amount was retained in order to work in pre-tangerine whistle - EVM versions) + * Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature. Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. diff --git a/docs/types.rst b/docs/types.rst index 5c291f35d8a9..ebc753a0d204 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -107,6 +107,9 @@ Operators: * ``<=``, ``<``, ``==``, ``!=``, ``>=`` and ``>`` +.. note:: + Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. + .. _members-of-addresses: Members of Addresses diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a3cbe50a2af8..ff5195ff5953 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1616,9 +1616,10 @@ string ContractType::canonicalName() const return m_contract.annotation().canonicalName; } -MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const +MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _contract) const { MemberList::MemberMap members; + solAssert(_contract, ""); if (m_super) { // add the most derived of all functions which are visible in derived contracts @@ -1660,7 +1661,9 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con &it.second->declaration() )); } - addNonConflictingAddressMembers(members); + // In 0.5.0 address members are not populated into the contract. + if (!_contract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + addNonConflictingAddressMembers(members); return members; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 350d41f17292..738e0a8701de 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7100,6 +7100,64 @@ BOOST_AUTO_TEST_CASE(array_length_validation) CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } +BOOST_AUTO_TEST_CASE(no_address_members_on_contract) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.balance; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"balance\" not found or not visible after argument-dependent lookup in contract"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.transfer; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"transfer\" not found or not visible after argument-dependent lookup in contract"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.send; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"send\" not found or not visible after argument-dependent lookup in contract"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.call; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"call\" not found or not visible after argument-dependent lookup in contract"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.callcode; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"callcode\" not found or not visible after argument-dependent lookup in contract"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + this.delegatecall; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"delegatecall\" not found or not visible after argument-dependent lookup in contract"); +} + BOOST_AUTO_TEST_SUITE_END() } From 81519845bc35043c8460252e62a30a137f93432d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 3 Oct 2017 15:28:29 +0100 Subject: [PATCH 073/108] Require location keyword for local variables (0.5.0) --- Changelog.md | 1 + libsolidity/analysis/ReferencesResolver.cpp | 18 +++++++++++++----- .../SolidityNameAndTypeResolution.cpp | 14 +++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index ace9bc361a4d..d558fd6fdf75 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Features: * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. * Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature. + * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 20016112e40d..29278332517d 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -298,11 +298,19 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) { typeLoc = DataLocation::Storage; if (_variable.isLocalVariable()) - m_errorReporter.warning( - _variable.location(), - "Variable is declared as a storage pointer. " - "Use an explicit \"storage\" keyword to silence this warning." - ); + { + if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + typeError( + _variable.location(), + "Storage location must be specified as either \"memory\" or \"storage\"." + ); + else + m_errorReporter.warning( + _variable.location(), + "Variable is declared as a storage pointer. " + "Use an explicit \"storage\" keyword to silence this warning." + ); + } } } else diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 738e0a8701de..a6fc4e341e27 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6523,7 +6523,19 @@ BOOST_AUTO_TEST_CASE(warn_unspecified_storage) } } )"; - CHECK_WARNING(text, "is declared as a storage pointer. Use an explicit \"storage\" keyword to silence this warning"); + CHECK_WARNING(text, "Variable is declared as a storage pointer. Use an explicit \"storage\" keyword to silence this warning"); + text = R"( + pragma experimental "v0.5.0"; + contract C { + struct S { uint a; } + S x; + function f() view public { + S y = x; + y; + } + } + )"; + CHECK_ERROR(text, TypeError, "Storage location must be specified as either \"memory\" or \"storage\"."); } BOOST_AUTO_TEST_CASE(implicit_conversion_disallowed) From b8be060b30d7c47d7c967291d24b5f0b4bf6cbff Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Oct 2017 19:31:32 +0100 Subject: [PATCH 074/108] Ensure unused variables are not warned for in interfaces/abstract contracts --- .../SolidityNameAndTypeResolution.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a6fc4e341e27..c3dacc3dd045 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6210,6 +6210,26 @@ BOOST_AUTO_TEST_CASE(warn_unused_return_parameter) CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(no_unused_warning_interface_arguments) +{ + char const* text = R"( + interface I { + function f(uint a) pure public returns (uint b); + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(no_unused_warning_abstract_arguments) +{ + char const* text = R"( + contract C { + function f(uint a) pure public returns (uint b); + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(no_unused_warnings) { char const* text = R"( From c28ed2a6191fd16c4be92a9adb53d5ff3215a34d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Oct 2017 20:08:12 +0100 Subject: [PATCH 075/108] Add tests for ConstantEvaluator --- .../SolidityNameAndTypeResolution.cpp | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a6fc4e341e27..9972d7951519 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7102,7 +7102,7 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(array_length_validation) +BOOST_AUTO_TEST_CASE(array_length_too_large) { char const* text = R"( contract C { @@ -7112,6 +7112,44 @@ BOOST_AUTO_TEST_CASE(array_length_validation) CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } +BOOST_AUTO_TEST_CASE(array_length_not_convertible_to_integer) +{ + char const* text = R"( + contract C { + uint[true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); +} + +BOOST_AUTO_TEST_CASE(array_length_invalid_expression) +{ + char const* text = R"( + contract C { + uint[-true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[true/1] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[1/true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[1.111111E1111111111111] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid literal value."); +} + BOOST_AUTO_TEST_CASE(no_address_members_on_contract) { char const* text = R"( From ed62b2583cf96a970dd610fa3ce837942bb67500 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Oct 2017 20:17:54 +0100 Subject: [PATCH 076/108] Use the proper error reporting interface in ConstantEvaluator --- libsolidity/analysis/ConstantEvaluator.cpp | 10 +++++----- libsolidity/analysis/ConstantEvaluator.h | 8 +++++++- libsolidity/analysis/ReferencesResolver.cpp | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 7057eab7cc03..6636ad97647d 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -22,17 +22,17 @@ #include #include +#include using namespace std; using namespace dev; using namespace dev::solidity; - void ConstantEvaluator::endVisit(UnaryOperation const& _operation) { TypePointer const& subType = _operation.subExpression().annotation().type; if (!dynamic_cast(subType.get())) - BOOST_THROW_EXCEPTION(_operation.subExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.subExpression().location(), "Invalid constant expression."); TypePointer t = subType->unaryOperatorResult(_operation.getOperator()); _operation.annotation().type = t; } @@ -42,9 +42,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) TypePointer const& leftType = _operation.leftExpression().annotation().type; TypePointer const& rightType = _operation.rightExpression().annotation().type; if (!dynamic_cast(leftType.get())) - BOOST_THROW_EXCEPTION(_operation.leftExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.leftExpression().location(), "Invalid constant expression."); if (!dynamic_cast(rightType.get())) - BOOST_THROW_EXCEPTION(_operation.rightExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.rightExpression().location(), "Invalid constant expression."); TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType); if (Token::isCompareOp(_operation.getOperator())) commonType = make_shared(); @@ -55,5 +55,5 @@ void ConstantEvaluator::endVisit(Literal const& _literal) { _literal.annotation().type = Type::forLiteral(_literal); if (!_literal.annotation().type) - BOOST_THROW_EXCEPTION(_literal.createTypeError("Invalid literal value.")); + m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value."); } diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 9ec04ebe58af..90bceb5d2b1e 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -29,6 +29,7 @@ namespace dev namespace solidity { +class ErrorReporter; class TypeChecker; /** @@ -37,13 +38,18 @@ class TypeChecker; class ConstantEvaluator: private ASTConstVisitor { public: - ConstantEvaluator(Expression const& _expr) { _expr.accept(*this); } + ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter): + m_errorReporter(_errorReporter) + { + _expr.accept(*this); + } private: virtual void endVisit(BinaryOperation const& _operation); virtual void endVisit(UnaryOperation const& _operation); virtual void endVisit(Literal const& _literal); + ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 29278332517d..f22c95cc1878 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -147,7 +147,7 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) if (Expression const* length = _typeName.length()) { if (!length->annotation().type) - ConstantEvaluator e(*length); + ConstantEvaluator e(*length, m_errorReporter); auto const* lengthType = dynamic_cast(length->annotation().type.get()); if (!lengthType || !lengthType->mobileType()) fatalTypeError(length->location(), "Invalid array length, expected integer literal."); From 475b81880185e816db9a962a06cb3c323b953a90 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Oct 2017 20:18:46 +0100 Subject: [PATCH 077/108] Remove obsolete createTypeError in AST --- libsolidity/ast/AST.cpp | 6 ------ libsolidity/ast/AST.h | 5 ----- libsolidity/ast/Types.cpp | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a805322b831f..1048b610cd99 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -73,11 +72,6 @@ ASTAnnotation& ASTNode::annotation() const return *m_annotation; } -Error ASTNode::createTypeError(string const& _description) const -{ - return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description); -} - SourceUnitAnnotation& SourceUnit::annotation() const { if (!m_annotation) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 75b8e94616e8..733e7c78c560 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -89,10 +88,6 @@ class ASTNode: private boost::noncopyable /// Returns the source code location of this node. SourceLocation const& location() const { return m_location; } - /// Creates a @ref TypeError exception and decorates it with the location of the node and - /// the given description - Error createTypeError(std::string const& _description) const; - ///@todo make this const-safe by providing a different way to access the annotation virtual ASTAnnotation& annotation() const; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ff5195ff5953..ee5f462b307c 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2025,7 +2025,7 @@ unsigned EnumType::memberValue(ASTString const& _member) const return index; ++index; } - BOOST_THROW_EXCEPTION(m_enum.createTypeError("Requested unknown enum value ." + _member)); + solAssert(false, "Requested unknown enum value " + _member); } bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const From c45e55675c57459d800391579e993975e3ad0291 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 3 Oct 2017 18:30:31 +0100 Subject: [PATCH 078/108] Force interface functions as external (0.5.0) --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 12 ++++++++-- .../SolidityNameAndTypeResolution.cpp | 22 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index d558fd6fdf75..d78dbbba89a1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Features: * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. * Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature. + * Type Checker: Force interface functions to be external as experimental 0.5.0 feature. * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. Bugfixes: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index b2a8805952ec..c2fba56509ab 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -595,8 +595,16 @@ bool TypeChecker::visit(FunctionDefinition const& _function) { if (_function.isImplemented()) m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation."); - if (_function.visibility() < FunctionDefinition::Visibility::Public) - m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private."); + if (_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + { + if (_function.visibility() != FunctionDefinition::Visibility::External) + m_errorReporter.typeError(_function.location(), "Functions in interfaces must be declared external."); + } + else + { + if (_function.visibility() < FunctionDefinition::Visibility::Public) + m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private."); + } if (_function.isConstructor()) m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in interfaces."); } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 903e73087a30..2c720d031266 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -5879,6 +5879,28 @@ BOOST_AUTO_TEST_CASE(interface_function_bodies) CHECK_ERROR(text, TypeError, "Functions in interfaces cannot have an implementation"); } +BOOST_AUTO_TEST_CASE(interface_function_external) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() external; + } + )"; + success(text); +} + +BOOST_AUTO_TEST_CASE(interface_function_public) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() public; + } + )"; + CHECK_ERROR(text, TypeError, "Functions in interfaces must be declared external."); +} + BOOST_AUTO_TEST_CASE(interface_function_internal) { char const* text = R"( From 71a819654e3c46aee92b831b835887ea200944f0 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Tue, 3 Oct 2017 18:28:45 +0100 Subject: [PATCH 079/108] Allow trailing slash in solc -allow-paths. --- solc/CommandLineInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 271511d4f611..36fcc1a40eda 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -717,7 +717,7 @@ bool CommandLineInterface::processInput() { vector paths; for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as(), boost::is_any_of(","))) - m_allowedDirectories.push_back(boost::filesystem::path(path)); + m_allowedDirectories.push_back(boost::filesystem::path(path).remove_trailing_separator()); } if (m_args.count(g_argStandardJSON)) From a458100175fa2b6d265ec939ae12b95ee89acb13 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Thu, 5 Oct 2017 11:53:32 +0100 Subject: [PATCH 080/108] Do not use remove_trailing_separator from Boost 1.58 as 1.56 is required --- solc/CommandLineInterface.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 36fcc1a40eda..1686dc2e49a9 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -716,8 +716,17 @@ bool CommandLineInterface::processInput() if (m_args.count(g_argAllowPaths)) { vector paths; - for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as(), boost::is_any_of(","))) - m_allowedDirectories.push_back(boost::filesystem::path(path).remove_trailing_separator()); + for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as(), boost::is_any_of(","))) { + auto filesystem_path = boost::filesystem::path(path); + // If the given path had a trailing slash, the Boost filesystem + // path will have it's last component set to '.'. This breaks + // path comparison in later parts of the code, so we need to strip + // it. + if (filesystem_path.filename() == ".") { + filesystem_path.remove_filename(); + } + m_allowedDirectories.push_back(filesystem_path); + } } if (m_args.count(g_argStandardJSON)) From d9004813d8b08c995787c2e614730b2b986186f0 Mon Sep 17 00:00:00 2001 From: Boris Kostenko Date: Mon, 9 Oct 2017 02:57:01 +0300 Subject: [PATCH 081/108] fix Appveyor PR test (issue #2272) Resolve issue #2272. Skip bytecode compare if deploy key is not available. This is the case for PR builds. --- appveyor.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b50681b96c5b..c63414b3c505 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,10 +47,12 @@ environment: #init: # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) install: - - ps: $fileContent = "-----BEGIN RSA PRIVATE KEY-----`n" - - ps: $fileContent += $env:priv_key.Replace(' ', "`n") - - ps: $fileContent += "`n-----END RSA PRIVATE KEY-----`n" - - ps: Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent + - ps: if ($env:priv_key) { + $fileContent = "-----BEGIN RSA PRIVATE KEY-----`n"; + $fileContent += $env:priv_key.Replace(' ', "`n"); + $fileContent += "`n-----END RSA PRIVATE KEY-----`n"; + Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent + } - git submodule update --init --recursive - ps: $prerelease = "nightly." - ps: $prerelease += Get-Date -format "yyyy.M.d" @@ -66,7 +68,10 @@ build_script: - cd %APPVEYOR_BUILD_FOLDER% - scripts\release.bat %CONFIGURATION% - ps: $bytecodedir = git show -s --format="%cd-%H" --date=short - - ps: scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir +# Skip bytecode compare if private key is not available + - ps: if ($env:priv_key) { + scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir + } test_script: - cd %APPVEYOR_BUILD_FOLDER% From 9ee619c9bba5cdbabfa9d587a0c726d1eaae9be9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 9 Oct 2017 10:09:20 +0100 Subject: [PATCH 082/108] Snarks test using Byzantium precompiles * Snark tests. * Verifying routine. * Example proof. * Update precompiled positions to Byzantium ruleset. --- test/RPCSession.cpp | 5 +- test/libsolidity/SolidityEndToEndTest.cpp | 301 ++++++++++++++++++++++ 2 files changed, 305 insertions(+), 1 deletion(-) diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 768c8c4bbd8f..72b2645359cc 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -236,7 +236,10 @@ void RPCSession::test_setChainParams(vector const& _accounts) "0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, "0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, "0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000006": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_add", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000007": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_mul", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000008": { "wei": "1", "precompiled": { "name": "alt_bn128_pairing_product", "linear": { "base": 15, "word": 3 } } } } } )"; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 35916ec7f9eb..ac77a7e14676 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10176,6 +10176,307 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); } +BOOST_AUTO_TEST_CASE(snark) +{ + char const* sourceCode = R"( + library Pairing { + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } + + /// @return the generator of G1 + function P1() internal returns (G1Point) { + return G1Point(1, 2); + } + + /// @return the generator of G2 + function P2() internal returns (G2Point) { + return G2Point( + [11559732032986387107991004021392285783925812861821192530917403151452391805634, + 10857046999023057135944570762232829481370756359578518086990519993285655852781], + [4082367875863433681332203403145435568316851327593401208105741076214120093531, + 8495653923123431417604973247489272438418190587263600148770280649306958101930] + ); + } + + /// @return the negation of p, i.e. p.add(p.negate()) should be zero. + function negate(G1Point p) internal returns (G1Point) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + + /// @return the sum of two points of G1 + function add(G1Point p1, G1Point p2) internal returns (G1Point r) { + uint[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + bool success; + assembly { + success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @return the product of a point on G1 and a scalar, i.e. + /// p == p.mul(1) and p.add(p) == p.mul(2) for all points p. + function mul(G1Point p, uint s) internal returns (G1Point r) { + uint[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + bool success; + assembly { + success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @return the result of computing the pairing check + /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 + /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should + /// return true. + function pairing(G1Point[] p1, G2Point[] p2) internal returns (bool) { + require(p1.length == p2.length); + uint elements = p1.length; + uint inputSize = p1.length * 6; + uint[] memory input = new uint[](inputSize); + for (uint i = 0; i < elements; i++) + { + input[i * 6 + 0] = p1[i].X; + input[i * 6 + 1] = p1[i].Y; + input[i * 6 + 2] = p2[i].X[0]; + input[i * 6 + 3] = p2[i].X[1]; + input[i * 6 + 4] = p2[i].Y[0]; + input[i * 6 + 5] = p2[i].Y[1]; + } + uint[1] memory out; + bool success; + assembly { + success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + return out[0] != 0; + } + function pairingProd2(G1Point a1, G2Point a2, G1Point b1, G2Point b2) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + function pairingProd3( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + function pairingProd4( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2, + G1Point d1, G2Point d2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new G2Point[](4); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p1[3] = d1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + p2[3] = d2; + return pairing(p1, p2); + } + } + + contract Test { + using Pairing for *; + struct VerifyingKey { + Pairing.G2Point A; + Pairing.G1Point B; + Pairing.G2Point C; + Pairing.G2Point gamma; + Pairing.G1Point gammaBeta1; + Pairing.G2Point gammaBeta2; + Pairing.G2Point Z; + Pairing.G1Point[] IC; + } + struct Proof { + Pairing.G1Point A; + Pairing.G1Point A_p; + Pairing.G2Point B; + Pairing.G1Point B_p; + Pairing.G1Point C; + Pairing.G1Point C_p; + Pairing.G1Point K; + Pairing.G1Point H; + } + function f() returns (bool) { + Pairing.G1Point memory p1; + Pairing.G1Point memory p2; + p1.X = 1; p1.Y = 2; + p2.X = 1; p2.Y = 2; + var explict_sum = Pairing.add(p1, p2); + var scalar_prod = Pairing.mul(p1, 2); + return (explict_sum.X == scalar_prod.X && + explict_sum.Y == scalar_prod.Y); + } + function g() returns (bool) { + Pairing.G1Point memory x = Pairing.add(Pairing.P1(), Pairing.negate(Pairing.P1())); + // should be zero + return (x.X == 0 && x.Y == 0); + } + function testMul() returns (bool) { + Pairing.G1Point memory p; + // @TODO The points here are reported to be not well-formed + p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726; + p.Y = 16229134936871442251132173501211935676986397196799085184804749187146857848057; + p = Pairing.mul(p, 13986731495506593864492662381614386532349950841221768152838255933892789078521); + return + p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 && + p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803; + } + function pair() returns (bool) { + Pairing.G2Point memory fiveTimesP2 = Pairing.G2Point( + [4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072], + [11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846] + ); + // The prime p in the base field F_p for G1 + uint p = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + Pairing.G1Point[] memory g1points = new Pairing.G1Point[](2); + Pairing.G2Point[] memory g2points = new Pairing.G2Point[](2); + // check e(5 P1, P2)e(-P1, 5 P2) == 1 + g1points[0] = Pairing.P1().mul(5); + g1points[1] = Pairing.P1().negate(); + g2points[0] = Pairing.P2(); + g2points[1] = fiveTimesP2; + if (!Pairing.pairing(g1points, g2points)) + return false; + // check e(P1, P2)e(-P1, P2) == 1 + g1points[0] = Pairing.P1(); + g1points[1] = Pairing.P1(); + g1points[1].Y = p - g1points[1].Y; + g2points[0] = Pairing.P2(); + g2points[1] = Pairing.P2(); + if (!Pairing.pairing(g1points, g2points)) + return false; + return true; + } + function verifyingKey() internal returns (VerifyingKey vk) { + vk.A = Pairing.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]); + vk.B = Pairing.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84); + vk.C = Pairing.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]); + vk.gamma = Pairing.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]); + vk.gammaBeta1 = Pairing.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d); + vk.gammaBeta2 = Pairing.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]); + vk.Z = Pairing.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]); + vk.IC = new Pairing.G1Point[](10); + vk.IC[0] = Pairing.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf); + vk.IC[1] = Pairing.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb); + vk.IC[2] = Pairing.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db); + vk.IC[3] = Pairing.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1); + vk.IC[4] = Pairing.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b); + vk.IC[5] = Pairing.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7); + vk.IC[6] = Pairing.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4); + vk.IC[7] = Pairing.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e); + vk.IC[8] = Pairing.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e); + vk.IC[9] = Pairing.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30); + } + function verify(uint[] input, Proof proof) internal returns (uint) { + VerifyingKey memory vk = verifyingKey(); + require(input.length + 1 == vk.IC.length); + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + for (uint i = 0; i < input.length; i++) + vk_x = Pairing.add(vk_x, Pairing.mul(vk.IC[i + 1], input[i])); + vk_x = Pairing.add(vk_x, vk.IC[0]); + if (!Pairing.pairingProd2(proof.A, vk.A, Pairing.negate(proof.A_p), Pairing.P2())) return 1; + if (!Pairing.pairingProd2(vk.B, proof.B, Pairing.negate(proof.B_p), Pairing.P2())) return 2; + if (!Pairing.pairingProd2(proof.C, vk.C, Pairing.negate(proof.C_p), Pairing.P2())) return 3; + if (!Pairing.pairingProd3( + proof.K, vk.gamma, + Pairing.negate(Pairing.add(vk_x, Pairing.add(proof.A, proof.C))), vk.gammaBeta2, + Pairing.negate(vk.gammaBeta1), proof.B + )) return 4; + if (!Pairing.pairingProd3( + Pairing.add(vk_x, proof.A), proof.B, + Pairing.negate(proof.H), vk.Z, + Pairing.negate(proof.C), Pairing.P2() + )) return 5; + return 0; + } + event Verified(string); + function verifyTx() returns (bool) { + uint[] memory input = new uint[](9); + Proof memory proof; + proof.A = Pairing.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497); + proof.A_p = Pairing.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366); + proof.B = Pairing.G2Point( + [8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055], + [15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]); + proof.B_p = Pairing.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950); + proof.C = Pairing.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506); + proof.C_p = Pairing.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686); + proof.H = Pairing.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758); + proof.K = Pairing.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170); + input[0] = 13986731495506593864492662381614386532349950841221768152838255933892789078521; + input[1] = 622860516154313070522697309645122400675542217310916019527100517240519630053; + input[2] = 11094488463398718754251685950409355128550342438297986977413505294941943071569; + input[3] = 6627643779954497813586310325594578844876646808666478625705401786271515864467; + input[4] = 2957286918163151606545409668133310005545945782087581890025685458369200827463; + input[5] = 1384290496819542862903939282897996566903332587607290986044945365745128311081; + input[6] = 5613571677741714971687805233468747950848449704454346829971683826953541367271; + input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807; + input[8] = 18066496933330839731877828156604; + if (verify(input, proof) == 0) { + Verified("Transaction successfully verified."); + return true; + } else { + return false; + } + } + + } + )"; + compileAndRun(sourceCode, 0, "Pairing"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Pairing", m_contractAddress}}); + // Disabled because the point seems to be not well-formed, we need to find another example. + //BOOST_CHECK(callContractFunction("testMul()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("pair()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("verifyTx()") == encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } From 81f9f86ce51d2e9b54bf76b1169f12e193c79745 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 10 Oct 2017 16:54:29 +0100 Subject: [PATCH 083/108] Add reference to EIP-55 in address literals (#3062) --- docs/types.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/types.rst b/docs/types.rst index ebc753a0d204..774c1d04dc1f 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -243,6 +243,9 @@ Hexadecimal literals that are between 39 and 41 digits long and do not pass the checksum test produce a warning and are treated as regular rational number literals. +.. note:: + The mixed-case address checksum format is defined in `EIP-55 `_. + .. index:: literal, literal;rational .. _rational_literals: From 15517b571d3ac4ee01af3e2e2f3fff7c5b2296c5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 13 Oct 2017 02:04:36 +0100 Subject: [PATCH 084/108] lll: disallow useless PUSHn in assembly --- liblll/CodeFragment.cpp | 44 ++++++++++++++++++++++++---------------- test/liblll/Compiler.cpp | 17 ++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index d4ef38883dc2..5c68194b4205 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -47,6 +47,32 @@ void CodeFragment::finalise(CompilerState const& _cs) } } +namespace +{ +/// Returns true iff the instruction is valid in "inline assembly". +bool validAssemblyInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) + ); +} + +/// Returns true iff the instruction is valid as a function. +bool validFunctionalInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) || + solidity::isDupInstruction(it->second) || + solidity::isSwapInstruction(it->second) || + it->second == solidity::Instruction::JUMPDEST + ); +} +} + CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM): m_readFile(_readFile) { @@ -80,7 +106,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback auto sr = _t.get, sp::utree_type::symbol_type>>(); string s(sr.begin(), sr.end()); string us = boost::algorithm::to_upper_copy(s); - if (_allowASM && c_instructions.count(us)) + if (_allowASM && c_instructions.count(us) && validAssemblyInstruction(us)) m_asm.append(c_instructions.at(us)); else if (_s.defs.count(s)) m_asm.append(_s.defs.at(s).m_asm); @@ -114,22 +140,6 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback } } -namespace -{ -/// Returns true iff the instruction is valid as a function. -bool validFunctionalInstruction(string us) -{ - auto it = c_instructions.find(us); - return !( - it == c_instructions.end() || - solidity::isPushInstruction(it->second) || - solidity::isDupInstruction(it->second) || - solidity::isSwapInstruction(it->second) || - it->second == solidity::Instruction::JUMPDEST - ); -} -} - void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { if (_t.tag() == 0 && _t.empty()) diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index 2d66bce1fe4f..77d263b8d08c 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -121,6 +121,23 @@ BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) BOOST_CHECK(!successCompile(sourceCode)); } +BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(asm PUSH" + boost::lexical_cast(i) + ")")); +} + +BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(JUMPDEST)")); +} + BOOST_AUTO_TEST_SUITE_END() } From 372c6693eaa6343858e5d9edfbe7e66cdc321f52 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 13 Oct 2017 13:33:18 +0100 Subject: [PATCH 085/108] Improve Z3 message in cmake --- libsolidity/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index f7c1a390e048..99612c402c43 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -6,9 +6,9 @@ find_package(Z3 QUIET) if (${Z3_FOUND}) include_directories(${Z3_INCLUDE_DIR}) add_definitions(-DHAVE_Z3) - message("Z3 SMT solver FOUND.") + message("Z3 SMT solver found. This enables optional SMT checking.") else() - message("Z3 SMT solver NOT found.") + message("Z3 SMT solver NOT found. Optional SMT checking will not be available. Please install Z3 if it is desired.") list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") endif() From e19843d9aa8b2ec6acd3ebdfed83eb5b1d4c0dfa Mon Sep 17 00:00:00 2001 From: Gianfranco Cecconi Date: Fri, 13 Oct 2017 16:01:59 +0100 Subject: [PATCH 086/108] Added boost-static to Fedora dependencies This fixes potential _cmake_ stage of the build, as documented here https://github.com/ethereum/solidity/issues/3071#issuecomment-336477742 . --- scripts/install_deps.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 01dee81d648a..49f864a06397 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -231,6 +231,7 @@ case $(uname -s) in autoconf \ automake \ boost-devel \ + boost-static \ cmake \ gcc \ gcc-c++ \ From 7c94e5462abb327016520b896178de41bea473c2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 13 Oct 2017 18:59:04 +0200 Subject: [PATCH 087/108] Assume peephole optimizer was successful if number of pops increased. --- Changelog.md | 1 + libevmasm/Assembly.cpp | 2 +- libevmasm/PeepholeOptimiser.cpp | 11 +++++++++-- test/libevmasm/Optimiser.cpp | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index d78dbbba89a1..22b5c00279bc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Features: * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. Bugfixes: + * Optimizer: Remove unused stack computation results. * Parser: Fix source location of VariableDeclarationStatement. * Type Checker: Properly check array length and don't rely on an assertion in code generation. * Type Checker: Properly support overwriting members inherited from ``address`` in a contract diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index df691e7dd163..37c4fb22df31 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -407,7 +407,7 @@ map Assembly::optimiseInternal( if (_settings.runPeephole) { PeepholeOptimiser peepOpt(m_items); - while (peepOpt.optimise()) + while (peepOpt.optimise() && count < 0xffffff) count++; } diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 31fdd3176dcf..168d11090ef4 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -249,6 +249,11 @@ void applyMethods(OptimiserState& _state, Method, OtherMethods... _other) applyMethods(_state, _other...); } +size_t numberOfPops(AssemblyItems const& _items) +{ + return std::count(_items.begin(), _items.end(), Instruction::POP); +} + } bool PeepholeOptimiser::optimise() @@ -257,8 +262,10 @@ bool PeepholeOptimiser::optimise() while (state.i < m_items.size()) applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); if (m_optimisedItems.size() < m_items.size() || ( - m_optimisedItems.size() == m_items.size() && - eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) + m_optimisedItems.size() == m_items.size() && ( + eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) || + numberOfPops(m_optimisedItems) > numberOfPops(m_items) + ) )) { m_items = std::move(m_optimisedItems); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 9dc49581067f..0ab95b080d08 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -841,6 +841,20 @@ BOOST_AUTO_TEST_CASE(peephole_double_push) ); } +BOOST_AUTO_TEST_CASE(peephole_pop_calldatasize) +{ + AssemblyItems items{ + u256(4), + Instruction::CALLDATASIZE, + Instruction::LT, + Instruction::POP + }; + PeepholeOptimiser peepOpt(items); + for (size_t i = 0; i < 3; i++) + BOOST_CHECK(peepOpt.optimise()); + BOOST_CHECK(items.empty()); +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ From afef6faeb6951ad147b28efa32c9839874aea890 Mon Sep 17 00:00:00 2001 From: walter-weinmann Date: Sat, 14 Oct 2017 15:48:14 +0200 Subject: [PATCH 088/108] grammar.txt: spelling error uixed. --- docs/grammar.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/grammar.txt b/docs/grammar.txt index 041728c566ff..72364b7c3672 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -145,7 +145,7 @@ Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | Fixed = 'fixed' | ( 'fixed' DecimalNumber 'x' DecimalNumber ) -Uixed = 'ufixed' | ( 'ufixed' DecimalNumber 'x' DecimalNumber ) +Ufixed = 'ufixed' | ( 'ufixed' DecimalNumber 'x' DecimalNumber ) InlineAssemblyBlock = '{' AssemblyItem* '}' From 4047ed23fcfe40e0cad66d566869b7ad771c8d8a Mon Sep 17 00:00:00 2001 From: David Au Date: Sun, 15 Oct 2017 11:04:00 -0400 Subject: [PATCH 089/108] Update miscellaneous.rst Fix small typo --- docs/miscellaneous.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 6c0efa9efa6f..1c4f918ca629 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -332,7 +332,7 @@ Global Variables - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` - ``super``: the contract one level higher in the inheritance hierarchy - ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address -- ``suicide(address recipieint)``: an alias to ``selfdestruct`` +- ``suicide(address recipient)``: an alias to ``selfdestruct`` - ``
.balance`` (``uint256``): balance of the :ref:`address` in Wei - ``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure - ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure From 082e7b6a9ea5f4651bed0b2ab037dbba05af26eb Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 16 Oct 2017 13:28:44 +0200 Subject: [PATCH 090/108] Allow ``gas`` in view functions. --- Changelog.md | 1 + libevmasm/SemanticInformation.cpp | 2 +- test/libsolidity/ViewPureChecker.cpp | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index d78dbbba89a1..ac27ca7fb255 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Bugfixes: (such as ``balance``, ``transfer``, etc.) * Type Checker: Prevent duplicate event declarations. * Type Checker: Do not mark event parameters as shadowing state variables. + * Type Checker: Allow ``gas`` in view functions. ### 0.4.17 (2017-09-21) diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 83cfe2c6d4cd..61a6ccda4461 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -198,6 +198,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::ORIGIN: case Instruction::CALLER: case Instruction::CALLVALUE: + case Instruction::GAS: case Instruction::GASPRICE: case Instruction::EXTCODESIZE: case Instruction::EXTCODECOPY: @@ -223,7 +224,6 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::SSTORE: case Instruction::JUMP: case Instruction::JUMPI: - case Instruction::GAS: case Instruction::LOG0: case Instruction::LOG1: case Instruction::LOG2: diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 8024151967d2..6353ae8a896c 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(assembly) assembly { x := 7 } } function g() view public { - assembly { for {} 1 { pop(sload(0)) } { } } + assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } } function h() view public { assembly { function g() { pop(blockhash(20)) } } @@ -357,6 +357,9 @@ BOOST_AUTO_TEST_CASE(assembly) function j() public { assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } } + function k() public { + assembly { pop(call(gas, 1, 2, 3, 4, 5, 6)) } + } } )"; CHECK_SUCCESS_NO_WARNINGS(text); @@ -367,7 +370,7 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) string text = R"( contract C { function i() view public { - assembly { pop(staticcall(0, 1, 2, 3, 4, 5)) } + assembly { pop(staticcall(gas, 1, 2, 3, 4, 5)) } } } )"; From 550653300b5deca3a26631eb883da68d72458bd6 Mon Sep 17 00:00:00 2001 From: Giovanni Casinelli Date: Mon, 16 Oct 2017 19:48:04 +0800 Subject: [PATCH 091/108] Update abi-spec.rst --- docs/abi-spec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 0361458f8bd3..43757d24e30f 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -279,7 +279,7 @@ Events Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract's address, a series of up to four topics and some arbitrary length binary data. Events leverage the existing function ABI in order to interpret this (together with an interface spec) as a properly typed structure. -Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3, are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which as not indexed form the byte array of the event. +Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3, are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which are not indexed form the byte array of the event. In effect, a log entry using this ABI is described as: From f5e91e4a94b01daf2bbde637abef1796f063c348 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 16 Oct 2017 18:45:21 +0200 Subject: [PATCH 092/108] Throw on too many peephole optimizer iterations. --- libevmasm/Assembly.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 37c4fb22df31..5fab24e191c4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -407,8 +407,11 @@ map Assembly::optimiseInternal( if (_settings.runPeephole) { PeepholeOptimiser peepOpt(m_items); - while (peepOpt.optimise() && count < 0xffffff) + while (peepOpt.optimise()) + { count++; + assertThrow(count < 64000, OptimizerException, "Peephole optimizer seems to be stuck."); + } } // This only modifies PushTags, we have to run again to actually remove code. From 09ff9282dff7f9b1b765a18984c80ab33e031d16 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 16 Oct 2017 22:18:12 +0200 Subject: [PATCH 093/108] Disable prepublish script in test. --- scripts/test_emscripten.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh index b01b33bb778a..d5823388a2d5 100755 --- a/scripts/test_emscripten.sh +++ b/scripts/test_emscripten.sh @@ -36,6 +36,10 @@ DIR=$(mktemp -d) echo "Preparing solc-js..." git clone --depth 1 https://github.com/ethereum/solc-js "$DIR" cd "$DIR" + # disable "prepublish" script which downloads the latest version + # (we will replace it anyway and it is often incorrectly cached + # on travis) + npm set script.prepublish '' npm install # Replace soljson with current build From 6001bd1406e7adbb6607485afb775bbb5b6c2ac3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 11 Oct 2017 12:28:21 +0200 Subject: [PATCH 094/108] Allocate one byte per memory byte array element instead of 32. --- Changelog.md | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 11 ++++++++-- test/libsolidity/SolidityEndToEndTest.cpp | 24 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index c8ea21f51320..ed3cdfeae6b1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Features: * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. Bugfixes: + * Code Generator: Allocate one byte per memory byte array element instead of 32. * Optimizer: Remove unused stack computation results. * Parser: Fix source location of VariableDeclarationStatement. * Type Checker: Properly check array length and don't rely on an assertion in code generation. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index fe37baac2741..bb8c4a94039a 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -858,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE; // Stack: memptr requested_length // update free memory pointer - m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize(); - m_context << Instruction::MUL << u256(32) << Instruction::ADD; + m_context << Instruction::DUP1; + // Stack: memptr requested_length requested_length + if (arrayType.isByteArray()) + // Round up to multiple of 32 + m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND; + else + m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL; + // stacK: memptr requested_length data_size + m_context << u256(32) << Instruction::ADD; m_context << Instruction::DUP3 << Instruction::ADD; utils().storeFreeMemoryPointer(); // Stack: memptr requested_length diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ac77a7e14676..648c13cbce17 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7309,6 +7309,30 @@ BOOST_AUTO_TEST_CASE(create_memory_array) ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B"))); } +BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) +{ + // Check allocation size of byte array. Should be 32 plus length rounded up to next + // multiple of 32 + char const* sourceCode = R"( + contract C { + function f() pure returns (uint d1, uint d2, uint d3) { + bytes memory b1 = new bytes(31); + bytes memory b2 = new bytes(32); + bytes memory b3 = new bytes(256); + bytes memory b4 = new bytes(31); + assembly { + d1 := sub(b2, b1) + d2 := sub(b3, b2) + d3 := sub(b4, b3) + } + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256)); +} + + BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) { // Computes binomial coefficients the chinese way From 9cab34292c3f3784ea53e430c67eb5e778e08b35 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 16 Oct 2017 18:47:42 +0200 Subject: [PATCH 095/108] Use new eth binary. --- scripts/tests.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/tests.sh b/scripts/tests.sh index bf3e34550ea1..f679ecc35453 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -42,8 +42,9 @@ elif [ -z $CI ]; then ETH_PATH="eth" else mkdir -p /tmp/test - wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium - test "$(shasum /tmp/test/eth)" = "6e16ae5e0a0079d85fd63fb43547be3c52410e7e /tmp/test/eth" + # Update hash below if binary is changed. + wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium2 + test "$(shasum /tmp/test/eth)" = "4dc3f208475f622be7c8e53bee720e14cd254c6f /tmp/test/eth" sync chmod +x /tmp/test/eth sync # Otherwise we might get a "text file busy" error From 0d6e6cc8f29584767d56e7a3063f0b1b2d47fe67 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 09:58:03 +0200 Subject: [PATCH 096/108] Quiet wget. --- scripts/tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests.sh b/scripts/tests.sh index f679ecc35453..2b47c2547128 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -43,7 +43,7 @@ elif [ -z $CI ]; then else mkdir -p /tmp/test # Update hash below if binary is changed. - wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium2 + wget -q -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium2 test "$(shasum /tmp/test/eth)" = "4dc3f208475f622be7c8e53bee720e14cd254c6f /tmp/test/eth" sync chmod +x /tmp/test/eth From 3bcaa24c5eeb452b09c8b9d0c9f207ac2696e218 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 18:55:55 +0200 Subject: [PATCH 097/108] Project moved. --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index b1d778903112..351f8ad7a8a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -62,7 +62,7 @@ Available Solidity Integrations * `Solium `_ A commandline linter for Solidity which strictly follows the rules prescribed by the `Solidity Style Guide `_. -* `Solhint `_ +* `Solhint `_ Solidity linter that provides security, style guide and best practice rules for smart contract validation. * `Visual Studio Code extension `_ From c99d2aae042643d9d26a4b952e07ca90f11a83c3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 18 Sep 2017 11:39:17 +0100 Subject: [PATCH 098/108] Validate each tuple literal --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 6 ++++ .../SolidityNameAndTypeResolution.cpp | 33 ++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index ed3cdfeae6b1..076df6066b92 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * Type Checker: Prevent duplicate event declarations. * Type Checker: Do not mark event parameters as shadowing state variables. * Type Checker: Allow ``gas`` in view functions. + * Type Checker: Validate each number literal in tuple expressions even if they are not assigned from. ### 0.4.17 (2017-09-21) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index c2fba56509ab..054912dd6157 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1293,6 +1293,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { components[i]->accept(*this); types.push_back(type(*components[i])); + + // Note: code generation will visit each of the expression even if they are not assigned from. + if (types[i]->category() == Type::Category::RationalNumber) + if (!dynamic_cast(*types[i]).mobileType()) + m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number."); + if (_tuple.isInlineArray()) solAssert(!!types[i], "Inline array cannot have empty components"); if (_tuple.isInlineArray()) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 2c720d031266..e9066c329304 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -5537,7 +5537,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid mobile type."); + CHECK_ERROR(text, TypeError, "Invalid rational number."); } BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) @@ -7096,6 +7096,37 @@ BOOST_AUTO_TEST_CASE(non_external_fallback) CHECK_ERROR(text, TypeError, "Fallback function must be defined as \"external\"."); } +BOOST_AUTO_TEST_CASE(invalid_literal_in_tuple) +{ + char const* text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1E111); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1, 1E111); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1E111, 1); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); +} + BOOST_AUTO_TEST_CASE(warn_about_sha3) { char const* text = R"( From 9d5c96ebdd9d118830458877682a746ab0c73fdc Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 19:10:31 +0200 Subject: [PATCH 099/108] Use config explicitly --- scripts/test_emscripten.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh index d5823388a2d5..4996e9577dad 100755 --- a/scripts/test_emscripten.sh +++ b/scripts/test_emscripten.sh @@ -39,7 +39,7 @@ DIR=$(mktemp -d) # disable "prepublish" script which downloads the latest version # (we will replace it anyway and it is often incorrectly cached # on travis) - npm set script.prepublish '' + npm config set script.prepublish '' npm install # Replace soljson with current build From 8a8a71de84f5bd71fcea4d31d5a53fde7820ead6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 19:14:49 +0200 Subject: [PATCH 100/108] Only check tuples for valid rational numbers if they have more than one element. --- libsolidity/analysis/TypeChecker.cpp | 2 +- .../SolidityNameAndTypeResolution.cpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 054912dd6157..746e762e8f8f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1295,7 +1295,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) types.push_back(type(*components[i])); // Note: code generation will visit each of the expression even if they are not assigned from. - if (types[i]->category() == Type::Category::RationalNumber) + if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1) if (!dynamic_cast(*types[i]).mobileType()) m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number."); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index e9066c329304..9b0647bf2cbc 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7106,7 +7106,7 @@ BOOST_AUTO_TEST_CASE(invalid_literal_in_tuple) } } )"; - CHECK_ERROR(text, TypeError, "Invalid rational number."); + CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type"); text = R"( contract C { function f() pure public { @@ -7125,6 +7125,22 @@ BOOST_AUTO_TEST_CASE(invalid_literal_in_tuple) } )"; CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + (2**270, 1); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + ((2**270) / 2**100, 1); + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(warn_about_sha3) From 1f97c1ea8fec9a755d767811731f57fd527747b5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 11:29:04 +0200 Subject: [PATCH 101/108] Rename variables in SMT checker. --- libsolidity/formal/SMTChecker.cpp | 18 +++++++++--------- libsolidity/formal/SMTChecker.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 7c8c089e338e..2d2f05ec2875 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -494,10 +494,10 @@ void SMTChecker::createVariable(VariableDeclaration const& _varDecl, bool _setTo { solAssert(m_currentSequenceCounter.count(&_varDecl) == 0, ""); solAssert(m_nextFreeSequenceCounter.count(&_varDecl) == 0, ""); - solAssert(m_Variables.count(&_varDecl) == 0, ""); + solAssert(m_variables.count(&_varDecl) == 0, ""); m_currentSequenceCounter[&_varDecl] = 0; m_nextFreeSequenceCounter[&_varDecl] = 1; - m_Variables.emplace(&_varDecl, m_interface->newFunction(uniqueSymbol(_varDecl), smt::Sort::Int, smt::Sort::Int)); + m_variables.emplace(&_varDecl, m_interface->newFunction(uniqueSymbol(_varDecl), smt::Sort::Int, smt::Sort::Int)); setValue(_varDecl, _setToZero); } else @@ -566,7 +566,7 @@ smt::Expression SMTChecker::maxValue(IntegerType const& _t) smt::Expression SMTChecker::expr(Expression const& _e) { - if (!m_Expressions.count(&_e)) + if (!m_expressions.count(&_e)) { solAssert(_e.annotation().type, ""); switch (_e.annotation().type->category()) @@ -575,24 +575,24 @@ smt::Expression SMTChecker::expr(Expression const& _e) { if (RationalNumberType const* rational = dynamic_cast(_e.annotation().type.get())) solAssert(!rational->isFractional(), ""); - m_Expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); break; } case Type::Category::Integer: - m_Expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); break; case Type::Category::Bool: - m_Expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e))); break; default: solAssert(false, "Type not implemented."); } } - return m_Expressions.at(&_e); + return m_expressions.at(&_e); } smt::Expression SMTChecker::var(Declaration const& _decl) { - solAssert(m_Variables.count(&_decl), ""); - return m_Variables.at(&_decl); + solAssert(m_variables.count(&_decl), ""); + return m_variables.at(&_decl); } diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index d23fd201b762..faaac6396fff 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -103,8 +103,8 @@ class SMTChecker: private ASTConstVisitor std::shared_ptr m_interface; std::map m_currentSequenceCounter; std::map m_nextFreeSequenceCounter; - std::map m_Expressions; - std::map m_Variables; + std::map m_expressions; + std::map m_variables; ErrorReporter& m_errorReporter; FunctionDefinition const* m_currentFunction = nullptr; From 114983e079ca29a70c776b46af5b59800e99d9f0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 28 Sep 2017 15:24:01 +0200 Subject: [PATCH 102/108] Missing forward declaration. --- libsolidity/ast/ASTForward.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index 157353681709..46675e51b48d 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -57,6 +57,7 @@ class UserDefinedTypeName; class FunctionTypeName; class Mapping; class ArrayTypeName; +class InlineAssembly; class Statement; class Block; class PlaceholderStatement; From a71c6faf0f7772c36596b170c8423e1cbcf07df4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 17 Oct 2017 17:43:58 +0100 Subject: [PATCH 103/108] Remove duplicate >= in Z3 --- libsolidity/formal/Z3Interface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 0ceed3a7eb4d..9eb79d29af96 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -118,8 +118,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) {">=", 2}, {"+", 2}, {"-", 2}, - {"*", 2}, - {">=", 2} + {"*", 2} }; string const& n = _expr.name; if (m_functions.count(n)) From 153ae988782bbe59ca301f4fa84babb59ae4f2e0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 11 Oct 2017 15:15:17 +0200 Subject: [PATCH 104/108] Catch exception in Z3. Note: This exception might not be the result of resource limitation, it might also hint towards usage error. --- libsolidity/formal/Z3Interface.cpp | 45 ++++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 9eb79d29af96..ab28baa3311d 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -73,28 +73,37 @@ void Z3Interface::addAssertion(Expression const& _expr) pair> Z3Interface::check(vector const& _expressionsToEvaluate) { CheckResult result; - switch (m_solver.check()) + vector values; + try { - case z3::check_result::sat: - result = CheckResult::SATISFIABLE; - break; - case z3::check_result::unsat: - result = CheckResult::UNSATISFIABLE; - break; - case z3::check_result::unknown: - result = CheckResult::UNKNOWN; - break; - default: - solAssert(false, ""); + switch (m_solver.check()) + { + case z3::check_result::sat: + result = CheckResult::SATISFIABLE; + break; + case z3::check_result::unsat: + result = CheckResult::UNSATISFIABLE; + break; + case z3::check_result::unknown: + result = CheckResult::UNKNOWN; + break; + default: + solAssert(false, ""); + } + + if (result != CheckResult::UNSATISFIABLE) + { + z3::model m = m_solver.get_model(); + for (Expression const& e: _expressionsToEvaluate) + values.push_back(toString(m.eval(toZ3Expr(e)))); + } } - - vector values; - if (result != CheckResult::UNSATISFIABLE) + catch (z3::exception const& _e) { - z3::model m = m_solver.get_model(); - for (Expression const& e: _expressionsToEvaluate) - values.push_back(toString(m.eval(toZ3Expr(e)))); + result = CheckResult::ERROR; + values.clear(); } + return make_pair(result, values); } From a3db1fc1976e1b2e67aedecb771c288b6dca6b1c Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 11 Oct 2017 10:45:24 +0200 Subject: [PATCH 105/108] Do not accept truncated function selectors. --- Changelog.md | 2 ++ libsolidity/codegen/ContractCompiler.cpp | 11 ++++------- test/libsolidity/SolidityEndToEndTest.cpp | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index ed3cdfeae6b1..c9e76ee5fe36 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,8 @@ Features: * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature (previously, some amount was retained in order to work in pre-tangerine whistle EVM versions) + * Code Generator: Do not accept data with less than four bytes (truncated function + signature) for regular function calls - fallback function is invoked instead. * Parser: Better error message for unexpected trailing comma in parameter lists. * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 429db5327c03..74565ae4b3ca 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -251,13 +251,10 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac FunctionDefinition const* fallback = _contract.fallbackFunction(); eth::AssemblyItem notFound = m_context.newTag(); - // shortcut messages without data if we have many functions in order to be able to receive - // ether with constant gas - if (interfaceFunctions.size() > 5 || fallback) - { - m_context << Instruction::CALLDATASIZE << Instruction::ISZERO; - m_context.appendConditionalJumpTo(notFound); - } + // directly jump to fallback if the data is too short to contain a function selector + // also guards against short data + m_context << u256(4) << Instruction::CALLDATASIZE << Instruction::LT; + m_context.appendConditionalJumpTo(notFound); // retrieve the function signature hash from the calldata if (!interfaceFunctions.empty()) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 648c13cbce17..9a83711308e0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2899,6 +2899,25 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(short_data_calls_fallback) +{ + char const* sourceCode = R"( + contract A { + uint public x; + // Signature is d88e0b00 + function fow() { x = 3; } + function () { x = 2; } + } + )"; + compileAndRun(sourceCode); + // should call fallback + sendMessage(asBytes("\xd8\x8e\x0b"), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); + // should call function + sendMessage(asBytes(string("\xd8\x8e\x0b") + string(1, 0)), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(event) { char const* sourceCode = R"( From 58139e8613e64bc5a921478d153ae9a130ca9772 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 11 Oct 2017 12:52:14 +0200 Subject: [PATCH 106/108] Adjust tests. --- test/libsolidity/Assembly.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 56ac8cf5cb78..358d3c72074c 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr n = make_shared(""); AssemblyItems items = compileContract(sourceCode); vector locations = - vector(18, SourceLocation(2, 75, n)) + + vector(24, SourceLocation(2, 75, n)) + vector(32, SourceLocation(20, 72, n)) + vector{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector(2, SourceLocation(58, 67, n)) + From 7849b920cf3ba6502f8a45e0c35be6393392cc00 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 16 Oct 2017 22:27:27 +0200 Subject: [PATCH 107/108] Bug list entry. --- docs/bugs.json | 7 ++++++ docs/bugs.rst | 2 +- docs/bugs_by_version.json | 45 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/docs/bugs.json b/docs/bugs.json index ac322a486e19..c642793a8c68 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,11 @@ [ + { + "name": "ZeroFunctionSelector", + "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.", + "description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.", + "fixed": "0.4.18", + "severity": "very low" + }, { "name": "DelegateCallReturnValue", "summary": "The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.", diff --git a/docs/bugs.rst b/docs/bugs.rst index 55771a354e11..7629830df456 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -48,7 +48,7 @@ fixed publish The date at which the bug became known publicly, optional severity - Severity of the bug: low, medium, high. Takes into account + Severity of the bug: very low, low, medium, high. Takes into account discoverability in contract tests, likelihood of occurrence and potential damage by exploits. conditions diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index c3686ebfdf1b..48881d0c0451 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -17,6 +18,7 @@ }, "0.1.1": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -33,6 +35,7 @@ }, "0.1.2": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -49,6 +52,7 @@ }, "0.1.3": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -65,6 +69,7 @@ }, "0.1.4": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -81,6 +86,7 @@ }, "0.1.5": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -97,6 +103,7 @@ }, "0.1.6": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -114,6 +121,7 @@ }, "0.1.7": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -131,6 +139,7 @@ }, "0.2.0": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -148,6 +157,7 @@ }, "0.2.1": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -165,6 +175,7 @@ }, "0.2.2": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -182,6 +193,7 @@ }, "0.3.0": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -199,6 +211,7 @@ }, "0.3.1": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -215,6 +228,7 @@ }, "0.3.2": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -231,6 +245,7 @@ }, "0.3.3": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -246,6 +261,7 @@ }, "0.3.4": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -261,6 +277,7 @@ }, "0.3.5": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -276,6 +293,7 @@ }, "0.3.6": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -289,6 +307,7 @@ }, "0.4.0": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -302,6 +321,7 @@ }, "0.4.1": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -315,6 +335,7 @@ }, "0.4.10": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -324,6 +345,7 @@ }, "0.4.11": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral" @@ -332,6 +354,7 @@ }, "0.4.12": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], @@ -339,6 +362,7 @@ }, "0.4.13": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], @@ -346,24 +370,32 @@ }, "0.4.14": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue" ], "released": "2017-07-31" }, "0.4.15": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-08-08" }, "0.4.16": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-08-24" }, "0.4.17": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-09-21" }, "0.4.2": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -376,6 +408,7 @@ }, "0.4.3": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -387,6 +420,7 @@ }, "0.4.4": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -397,6 +431,7 @@ }, "0.4.5": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -408,6 +443,7 @@ }, "0.4.6": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -418,6 +454,7 @@ }, "0.4.7": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -427,6 +464,7 @@ }, "0.4.8": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -436,6 +474,7 @@ }, "0.4.9": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", From c3a7422399f66c0ec9d84216a64a63b0368c7175 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 18 Oct 2017 12:28:18 +0200 Subject: [PATCH 108/108] Update changelog for 0.4.18 release. --- Changelog.md | 14 +++++++------- docs/bugs_by_version.json | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index f4caefd8e086..a8a613634cc8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,11 +1,9 @@ -### 0.4.18 (unreleased) +### 0.4.18 (2017-10-18) Features: * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature - (previously, some amount was retained in order to work in pre-tangerine whistle + (previously, some amount was retained in order to work in pre-Tangerine-Whistle EVM versions) - * Code Generator: Do not accept data with less than four bytes (truncated function - signature) for regular function calls - fallback function is invoked instead. * Parser: Better error message for unexpected trailing comma in parameter lists. * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. @@ -16,14 +14,16 @@ Features: Bugfixes: * Code Generator: Allocate one byte per memory byte array element instead of 32. + * Code Generator: Do not accept data with less than four bytes (truncated function + signature) for regular function calls - fallback function is invoked instead. * Optimizer: Remove unused stack computation results. * Parser: Fix source location of VariableDeclarationStatement. + * Type Checker: Allow ``gas`` in view functions. + * Type Checker: Do not mark event parameters as shadowing state variables. + * Type Checker: Prevent duplicate event declarations. * Type Checker: Properly check array length and don't rely on an assertion in code generation. * Type Checker: Properly support overwriting members inherited from ``address`` in a contract (such as ``balance``, ``transfer``, etc.) - * Type Checker: Prevent duplicate event declarations. - * Type Checker: Do not mark event parameters as shadowing state variables. - * Type Checker: Allow ``gas`` in view functions. * Type Checker: Validate each number literal in tuple expressions even if they are not assigned from. ### 0.4.17 (2017-09-21) diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 48881d0c0451..cca4542885e3 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -393,6 +393,10 @@ ], "released": "2017-09-21" }, + "0.4.18": { + "bugs": [], + "released": "2017-10-18" + }, "0.4.2": { "bugs": [ "ZeroFunctionSelector",