diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | docs/abi-spec.rst | 4 | ||||
-rw-r--r-- | docs/contracts.rst | 22 | ||||
-rw-r--r-- | libdevcore/SHA3.h | 9 | ||||
-rw-r--r-- | libevmasm/Assembly.cpp | 30 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 8 | ||||
-rw-r--r-- | libevmasm/JumpdestRemover.cpp | 68 | ||||
-rw-r--r-- | libevmasm/JumpdestRemover.h | 50 | ||||
-rw-r--r-- | libsolidity/analysis/DocStringAnalyser.cpp | 2 | ||||
-rw-r--r-- | libsolidity/interface/ABI.cpp | 19 | ||||
-rw-r--r-- | libsolidity/interface/Natspec.h | 27 | ||||
-rw-r--r-- | test/libevmasm/Optimiser.cpp | 84 | ||||
-rw-r--r-- | test/libsolidity/Assembly.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/JSONCompiler.cpp | 12 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 8 |
15 files changed, 278 insertions, 70 deletions
diff --git a/Changelog.md b/Changelog.md index f4915db1..c3482c4b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.17 (unreleased) Features: + * Optimizer: Add new optimization step to remove unused ``JUMPDEST``s. Bugfixes: diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index c0969cae..fffd9a2c 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -293,9 +293,9 @@ The JSON format for a contract's interface is given by an array of function and/ * `name`: the name of the parameter; * `type`: the canonical type of the parameter. - `outputs`: an array of objects similar to `inputs`, can be omitted if function doesn't return anything; -- `constant`: `true` if function is :ref:`specified to not modify blockchain state <view-functions>`); - `payable`: `true` if function accepts ether, defaults to `false`; -- `stateMutability`: a string with one of the following values: `pure` (:ref:`specified to not read blockchain state <pure-functions>`), `view` (same as `constant` above), `nonpayable` and `payable` (same as `payable` above). +- `stateMutability`: a string with one of the following values: `pure` (:ref:`specified to not read blockchain state <pure-functions>`), `view` (:ref:`specified to not modify the blockchain state <view-functions>`), `nonpayable` and `payable` (same as `payable` above). +- `constant`: `true` if function is either `pure` or `view` `type` can be omitted, defaulting to `"function"`. diff --git a/docs/contracts.rst b/docs/contracts.rst index 50e7f3d1..ef09d935 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -469,9 +469,20 @@ View Functions Functions can be declared ``view`` in which case they promise not to modify the state. +The following statements are considered modifying the state: + +#. Writing to state variables. +#. :ref:`Emitting events. <events>`. +#. :ref:`Creating other contracts <creating-contracts>`. +#. Using ``selfdestruct``. +#. Sending Ether via calls. +#. Calling any function not marked ``view`` or ``pure``. +#. Using low-level calls. +#. Using inline assembly that contains certain opcodes. + :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.16; contract C { function f(uint a, uint b) view returns (uint) { @@ -496,9 +507,16 @@ Pure Functions Functions can be declared ``pure`` in which case they promise not to read from or modify the state. +In addition to the list of state modifying statements explained above, the following are considered reading from the state: +#. Reading from state variables. +#. Accessing ``this.balance`` or ``<address>.balance``. +#. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). +#. Calling any function not marked ``pure``. +#. Using inline assembly that contains certain opcodes. + :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.16; contract C { function f(uint a, uint b) pure returns (uint) { diff --git a/libdevcore/SHA3.h b/libdevcore/SHA3.h index 1a561066..d1e2cc98 100644 --- a/libdevcore/SHA3.h +++ b/libdevcore/SHA3.h @@ -23,8 +23,9 @@ #pragma once +#include <libdevcore/FixedHash.h> + #include <string> -#include "FixedHash.h" namespace dev { @@ -47,10 +48,4 @@ inline h256 keccak256(std::string const& _input) { return keccak256(bytesConstRe /// Calculate Keccak-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash. template<unsigned N> inline h256 keccak256(FixedHash<N> const& _input) { return keccak256(_input.ref()); } -/// Calculate Keccak-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data. -inline std::string keccak256(std::string const& _input, bool _isNibbles) { return asString((_isNibbles ? keccak256(fromHex(_input)) : keccak256(bytesConstRef(&_input))).asBytes()); } - -/// Calculate Keccak-256 MAC -inline void keccak256mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) { keccak256(_secret.toBytes() + _plain.toBytes()).ref().populate(_output); } - } diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 0a3bf6b8..8c1f9296 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -24,6 +24,7 @@ #include <libevmasm/CommonSubexpressionEliminator.h> #include <libevmasm/ControlFlowGraph.h> #include <libevmasm/PeepholeOptimiser.h> +#include <libevmasm/JumpdestRemover.h> #include <libevmasm/BlockDeduplicator.h> #include <libevmasm/ConstantOptimiser.h> #include <libevmasm/GasMeter.h> @@ -349,6 +350,7 @@ Assembly& Assembly::optimise(bool _enable, bool _isCreation, size_t _runs) { OptimiserSettings settings; settings.isCreation = _isCreation; + settings.runJumpdestRemover = true; settings.runPeephole = true; if (_enable) { @@ -357,18 +359,21 @@ Assembly& Assembly::optimise(bool _enable, bool _isCreation, size_t _runs) settings.runConstantOptimiser = true; } settings.expectedExecutionsPerDeployment = _runs; - optimiseInternal(settings); + optimise(settings); return *this; } -Assembly& Assembly::optimise(OptimiserSettings _settings) +Assembly& Assembly::optimise(OptimiserSettings const& _settings) { - optimiseInternal(_settings); + optimiseInternal(_settings, {}); return *this; } -map<u256, u256> Assembly::optimiseInternal(OptimiserSettings _settings) +map<u256, u256> Assembly::optimiseInternal( + OptimiserSettings const& _settings, + std::set<size_t> const& _tagsReferencedFromOutside +) { // Run optimisation for sub-assemblies. for (size_t subId = 0; subId < m_subs.size(); ++subId) @@ -376,7 +381,10 @@ map<u256, u256> Assembly::optimiseInternal(OptimiserSettings _settings) OptimiserSettings settings = _settings; // Disable creation mode for sub-assemblies. settings.isCreation = false; - map<u256, u256> subTagReplacements = m_subs[subId]->optimiseInternal(settings); + map<u256, u256> subTagReplacements = m_subs[subId]->optimiseInternal( + settings, + JumpdestRemover::referencedTags(m_items, subId) + ); // Apply the replacements (can be empty). BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId); } @@ -387,6 +395,13 @@ map<u256, u256> Assembly::optimiseInternal(OptimiserSettings _settings) { count = 0; + if (_settings.runJumpdestRemover) + { + JumpdestRemover jumpdestOpt(m_items); + if (jumpdestOpt.optimise(_tagsReferencedFromOutside)) + count++; + } + if (_settings.runPeephole) { PeepholeOptimiser peepOpt(m_items); @@ -473,8 +488,9 @@ LinkerObject const& Assembly::assemble() const for (auto const& sub: m_subs) { sub->assemble(); - if (!sub->m_tagPositionsInBytecode.empty()) - subTagSize = max(subTagSize, *max_element(sub->m_tagPositionsInBytecode.begin(), sub->m_tagPositionsInBytecode.end())); + for (size_t tagPos: sub->m_tagPositionsInBytecode) + if (tagPos != size_t(-1) && tagPos > subTagSize) + subTagSize = tagPos; } LinkerObject& ret = m_assembledObject; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 451b4ea0..680cb1af 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -100,6 +100,7 @@ public: struct OptimiserSettings { bool isCreation = false; + bool runJumpdestRemover = false; bool runPeephole = false; bool runDeduplicate = false; bool runCSE = false; @@ -110,7 +111,7 @@ public: }; /// Execute optimisation passes as defined by @a _settings and return the optimised assembly. - Assembly& optimise(OptimiserSettings _settings); + Assembly& optimise(OptimiserSettings const& _settings); /// Modify (if @a _enable is set) and return the current assembly such that creation and /// execution gas usage is optimised. @a _isCreation should be true for the top-level assembly. @@ -128,8 +129,9 @@ public: protected: /// Does the same operations as @a optimise, but should only be applied to a sub and - /// returns the replaced tags. - std::map<u256, u256> optimiseInternal(OptimiserSettings _settings); + /// returns the replaced tags. Also takes an argument containing the tags of this assembly + /// that are referenced in a super-assembly. + std::map<u256, u256> optimiseInternal(OptimiserSettings const& _settings, std::set<size_t> const& _tagsReferencedFromOutside); unsigned bytesRequired(unsigned subTagSize) const; diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp new file mode 100644 index 00000000..b6016798 --- /dev/null +++ b/libevmasm/JumpdestRemover.cpp @@ -0,0 +1,68 @@ +/* + 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 <http://www.gnu.org/licenses/>. +*/ +/** + * @author Alex Beregszaszi + * Removes unused JUMPDESTs. + */ + +#include "JumpdestRemover.h" + +#include <libsolidity/interface/Exceptions.h> + +#include <libevmasm/AssemblyItem.h> + +using namespace std; +using namespace dev::eth; +using namespace dev; + + +bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside) +{ + set<size_t> references{referencedTags(m_items, -1)}; + references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); + + size_t initialSize = m_items.size(); + /// Remove tags which are never referenced. + auto pend = remove_if( + m_items.begin(), + m_items.end(), + [&](AssemblyItem const& _item) + { + if (_item.type() != Tag) + return false; + auto asmIdAndTag = _item.splitForeignPushTag(); + solAssert(asmIdAndTag.first == size_t(-1), "Sub-assembly tag used as label."); + size_t tag = asmIdAndTag.second; + return !references.count(tag); + } + ); + m_items.erase(pend, m_items.end()); + return m_items.size() != initialSize; +} + +set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) +{ + set<size_t> ret; + for (auto const& item: _items) + if (item.type() == PushTag) + { + auto subAndTag = item.splitForeignPushTag(); + if (subAndTag.first == _subId) + ret.insert(subAndTag.second); + } + return ret; +} diff --git a/libevmasm/JumpdestRemover.h b/libevmasm/JumpdestRemover.h new file mode 100644 index 00000000..2dad0927 --- /dev/null +++ b/libevmasm/JumpdestRemover.h @@ -0,0 +1,50 @@ +/* + 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 <http://www.gnu.org/licenses/>. +*/ +/** + * @author Alex Beregszaszi + * Removes unused JUMPDESTs. + */ +#pragma once + +#include <vector> +#include <cstddef> +#include <set> + +namespace dev +{ +namespace eth +{ +class AssemblyItem; +using AssemblyItems = std::vector<AssemblyItem>; + +class JumpdestRemover +{ +public: + explicit JumpdestRemover(AssemblyItems& _items): m_items(_items) {} + + bool optimise(std::set<size_t> const& _tagsReferencedFromOutside); + + /// @returns a set of all tags from the given sub-assembly that are referenced + /// from the given list of items. + static std::set<size_t> referencedTags(AssemblyItems const& _items, size_t _subId); + +private: + AssemblyItems& m_items; +}; + +} +} diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index 9a846b31..d08c4eb5 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -72,7 +72,7 @@ void DocStringAnalyser::handleCallable( DocumentedAnnotation& _annotation ) { - static const set<string> validTags = set<string>{"author", "dev", "notice", "return", "param", "why3"}; + static const set<string> validTags = set<string>{"author", "dev", "notice", "return", "param"}; parseDocStrings(_node, _annotation, validTags, "functions"); set<string> validParams; diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index 3df9d1f8..49df843d 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -32,13 +32,14 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) for (auto it: _contractDef.interfaceFunctions()) { auto externalFunctionType = it.second->interfaceFunctionType(); + solAssert(!!externalFunctionType, ""); Json::Value method; method["type"] = "function"; method["name"] = it.second->declaration().name(); // TODO: deprecate constant in a future release - method["constant"] = it.second->stateMutability() == StateMutability::Pure || it.second->stateMutability() == StateMutability::View; - method["payable"] = it.second->isPayable(); - method["stateMutability"] = stateMutabilityToString(it.second->stateMutability()); + method["constant"] = externalFunctionType->stateMutability() == StateMutability::Pure || it.second->stateMutability() == StateMutability::View; + method["payable"] = externalFunctionType->isPayable(); + method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( externalFunctionType->parameterNames(), externalFunctionType->parameterTypes(), @@ -53,15 +54,15 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) } if (_contractDef.constructor()) { + auto externalFunctionType = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType(); + solAssert(!!externalFunctionType, ""); Json::Value method; method["type"] = "constructor"; - auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType(); - solAssert(!!externalFunction, ""); - method["payable"] = externalFunction->isPayable(); - method["stateMutability"] = stateMutabilityToString(externalFunction->stateMutability()); + method["payable"] = externalFunctionType->isPayable(); + method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( - externalFunction->parameterNames(), - externalFunction->parameterTypes(), + externalFunctionType->parameterNames(), + externalFunctionType->parameterTypes(), _contractDef.isLibrary() ); abi.append(method); diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index 9ac3efea..0701f821 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -36,27 +36,8 @@ namespace solidity // Forward declarations class ContractDefinition; -class Type; -using TypePointer = std::shared_ptr<Type const>; struct DocTag; -enum class DocTagType: uint8_t -{ - None = 0, - Dev, - Notice, - Param, - Return, - Author, - Title -}; - -enum class CommentOwner -{ - Contract, - Function -}; - class Natspec { public: @@ -71,14 +52,6 @@ public: static Json::Value devDocumentation(ContractDefinition const& _contractDef); private: - /// @returns a json value suitable for a list of types in function input or output - /// parameters or other places. If @a _forLibrary is true, complex types are referenced - /// by name, otherwise they are anonymously expanded. - static Json::Value formatTypeList( - std::vector<std::string> const& _names, - std::vector<TypePointer> const& _types, - bool _forLibrary - ); /// @returns concatenation of all content under the given tag name. static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name); }; diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 6656f15b..9dc49581 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -22,6 +22,7 @@ #include <libevmasm/CommonSubexpressionEliminator.h> #include <libevmasm/PeepholeOptimiser.h> +#include <libevmasm/JumpdestRemover.h> #include <libevmasm/ControlFlowGraph.h> #include <libevmasm/BlockDeduplicator.h> #include <libevmasm/Assembly.h> @@ -840,6 +841,89 @@ BOOST_AUTO_TEST_CASE(peephole_double_push) ); } +BOOST_AUTO_TEST_CASE(jumpdest_removal) +{ + AssemblyItems items{ + AssemblyItem(Tag, 2), + AssemblyItem(PushTag, 1), + u256(5), + AssemblyItem(Tag, 10), + AssemblyItem(Tag, 3), + u256(6), + AssemblyItem(Tag, 1), + Instruction::JUMP, + }; + AssemblyItems expectation{ + AssemblyItem(PushTag, 1), + u256(5), + u256(6), + AssemblyItem(Tag, 1), + Instruction::JUMP + }; + JumpdestRemover jdr(items); + BOOST_REQUIRE(jdr.optimise({})); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) +{ + // This tests that tags from subassemblies are not removed + // if they are referenced by a super-assembly. Furthermore, + // tag unifications (due to block deduplication) is also + // visible at the super-assembly. + + Assembly main; + AssemblyPointer sub = make_shared<Assembly>(); + + sub->append(u256(1)); + auto t1 = sub->newTag(); + sub->append(t1); + sub->append(u256(2)); + sub->append(Instruction::JUMP); + auto t2 = sub->newTag(); + sub->append(t2); // Identical to T1, will be unified + sub->append(u256(2)); + sub->append(Instruction::JUMP); + auto t3 = sub->newTag(); + sub->append(t3); + auto t4 = sub->newTag(); + sub->append(t4); + auto t5 = sub->newTag(); + sub->append(t5); // This will be removed + sub->append(u256(7)); + sub->append(t4.pushTag()); + sub->append(Instruction::JUMP); + + size_t subId = size_t(main.appendSubroutine(sub).data()); + main.append(t1.toSubAssemblyTag(subId)); + main.append(t1.toSubAssemblyTag(subId)); + main.append(u256(8)); + + main.optimise(true); + + AssemblyItems expectationMain{ + AssemblyItem(PushSubSize, 0), + t1.toSubAssemblyTag(subId).pushTag(), + t1.toSubAssemblyTag(subId).pushTag(), + u256(8) + }; + BOOST_CHECK_EQUAL_COLLECTIONS( + main.items().begin(), main.items().end(), + expectationMain.begin(), expectationMain.end() + ); + + AssemblyItems expectationSub{ + u256(1), t1.tag(), u256(2), Instruction::JUMP, t4.tag(), u256(7), t4.pushTag(), Instruction::JUMP + }; + BOOST_CHECK_EQUAL_COLLECTIONS( + sub->items().begin(), sub->items().end(), + expectationSub.begin(), expectationSub.end() + ); +} + BOOST_AUTO_TEST_CASE(cse_sub_zero) { checkCSE({ diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 99a2996e..56ac8cf5 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -119,11 +119,11 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(19, SourceLocation(2, 75, n)) + + vector<SourceLocation>(18, SourceLocation(2, 75, n)) + vector<SourceLocation>(32, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(2, SourceLocation(58, 67, n)) + - vector<SourceLocation>(3, SourceLocation(20, 72, n)); + vector<SourceLocation>(2, SourceLocation(20, 72, n)); checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp index 0fe7636c..541cfbf0 100644 --- a/test/libsolidity/JSONCompiler.cpp +++ b/test/libsolidity/JSONCompiler.cpp @@ -120,18 +120,18 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00" + "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "60606040525b600080fd00" + "6060604052600080fd00" ); BOOST_CHECK(contract["functionHashes"].isObject()); BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[62,10800],\"external\":{},\"internal\":{}}" + "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); @@ -162,18 +162,18 @@ BOOST_AUTO_TEST_CASE(single_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00" + "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "60606040525b600080fd00" + "6060604052600080fd00" ); BOOST_CHECK(contract["functionHashes"].isObject()); BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[62,10800],\"external\":{},\"internal\":{}}" + "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 79848c36..24f915c0 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -198,19 +198,19 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), - "60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00" + "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" ); BOOST_CHECK(contract["evm"]["assembly"].isString()); BOOST_CHECK(contract["evm"]["assembly"].asString().find( " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x60)\n jumpi(tag_1, iszero(callvalue))\n" - " 0x0\n dup1\n revert\ntag_1:\ntag_2:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n" + " 0x0\n dup1\n revert\ntag_1:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n" " return\nstop\n\nsub_0: assembly {\n /* \"fileA\":0:14 contract A { } */\n" - " mstore(0x40, 0x60)\n tag_1:\n 0x0\n dup1\n revert\n\n" + " mstore(0x40, 0x60)\n 0x0\n dup1\n revert\n\n" " auxdata: 0xa165627a7a7230582") == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["evm"]["gasEstimates"]), - "{\"creation\":{\"codeDepositCost\":\"10800\",\"executionCost\":\"62\",\"totalCost\":\"10862\"}}" + "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"61\",\"totalCost\":\"10661\"}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); |