From 4ee7684afc9a01967a5f42eacfd0d365a58c5592 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 17 Feb 2022 09:39:54 +0100 Subject: [PATCH 01/45] Update PPA build script. --- scripts/release_ppa.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 725649f80..fe1efda27 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -55,9 +55,9 @@ keyid=379F4801D622CDCF email=builds@ethereum.org packagename=solc -static_build_distribution=hirsute +static_build_distribution=impish -DISTRIBUTIONS="focal hirsute impish jammy" +DISTRIBUTIONS="focal impish jammy" if is_release then From bf313444844407ad9614e5bc9f285c498834981a Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 17 Feb 2022 09:59:52 +0100 Subject: [PATCH 02/45] Add codeowners file. --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..1f6c29d6c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +docs/style-guide.rst @fulldecent From e9cc45b25886ab2fd023095b0607de777877d286 Mon Sep 17 00:00:00 2001 From: Wes Bouaziz <5843554+wesbz@users.noreply.github.com> Date: Thu, 17 Feb 2022 10:57:28 +0100 Subject: [PATCH 03/45] Fixing a typo in doc's EVM dialect in Yul's doc. It's the tiniest typo but it's visible on the website. --- docs/yul.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/yul.rst b/docs/yul.rst index 60a2da5b9..e4775ee4d 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -768,7 +768,7 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | Instruction | | | Explanation | +=========================+=====+===+=================================================================+ -| stop() + `-` | F | stop execution, identical to return(0, 0) | +| stop() | `-` | F | stop execution, identical to return(0, 0) | +-------------------------+-----+---+-----------------------------------------------------------------+ | add(x, y) | | F | x + y | +-------------------------+-----+---+-----------------------------------------------------------------+ From 175580fe90135b4449db057b8079756a6319e912 Mon Sep 17 00:00:00 2001 From: Marenz Date: Thu, 17 Feb 2022 16:52:36 +0100 Subject: [PATCH 04/45] Make error message less confusing --- libsolidity/analysis/ViewPureChecker.cpp | 5 ++--- .../syntaxTests/freeFunctions/free_mutability.sol | 2 +- .../libsolidity/syntaxTests/multiSource/one_source.sol | 2 +- .../viewPureChecker/access_to_base_member_function.sol | 2 +- .../viewPureChecker/access_to_base_member_struct.sol | 4 ++-- .../viewPureChecker/access_to_base_members.sol | 2 +- .../array/access_to_array_push_view.sol | 2 +- .../viewPureChecker/builtin_functions_view_fail.sol | 10 +++++----- .../viewPureChecker/call_internal_functions_fail.sol | 2 +- .../syntaxTests/viewPureChecker/creation_view_fail.sol | 2 +- .../viewPureChecker/function_types_fail.sol | 4 ++-- .../viewPureChecker/gas_with_call_nonpayable.sol | 4 ++-- .../viewPureChecker/local_storage_variables_fail.sol | 2 +- .../syntaxTests/viewPureChecker/modifiers_fail.sol | 2 +- .../viewPureChecker/value_with_call_nonpayable.sol | 4 ++-- .../syntaxTests/viewPureChecker/write_storage_fail.sol | 2 +- 16 files changed, 25 insertions(+), 26 deletions(-) diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 252210a12..3179a8eb7 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -256,10 +256,9 @@ void ViewPureChecker::reportMutability( m_errorReporter.typeError( 8961_error, _location, - "Function declared as " + + "Function cannot be declared as " + stateMutabilityToString(m_currentFunction->stateMutability()) + - ", but this expression (potentially) modifies the state and thus " - "requires non-payable (the default) or payable." + " because this expression (potentially) modifies the state." ); m_errors = true; } diff --git a/test/libsolidity/syntaxTests/freeFunctions/free_mutability.sol b/test/libsolidity/syntaxTests/freeFunctions/free_mutability.sol index dafa91ccb..9279ff1eb 100644 --- a/test/libsolidity/syntaxTests/freeFunctions/free_mutability.sol +++ b/test/libsolidity/syntaxTests/freeFunctions/free_mutability.sol @@ -5,4 +5,4 @@ function f() { function g(uint[] storage x) pure { x[0] = 1; } // ---- // Warning 2018: (0-39): Function state mutability can be restricted to pure -// TypeError 8961: (76-80): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (76-80): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/multiSource/one_source.sol b/test/libsolidity/syntaxTests/multiSource/one_source.sol index 11ee49720..9c1d92eb5 100644 --- a/test/libsolidity/syntaxTests/multiSource/one_source.sol +++ b/test/libsolidity/syntaxTests/multiSource/one_source.sol @@ -4,4 +4,4 @@ contract A { function f() public pure { x = 42; } } // ---- -// TypeError 8961: (SourceName:53-54): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (SourceName:53-54): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_function.sol b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_function.sol index 1b5a7ae50..0f434c743 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_function.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_function.sol @@ -8,4 +8,4 @@ contract B is A { } } // ---- -// TypeError 8961: (100-105): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (100-105): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_struct.sol b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_struct.sol index 612fbb745..13d0ed913 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_struct.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_member_struct.sol @@ -15,7 +15,7 @@ contract B is A { } } // ---- -// TypeError 8961: (107-110): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (166-171): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (107-110): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (166-171): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 2527: (244-247): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 2527: (244-249): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_members.sol b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_members.sol index e9dccaecd..1203d2c67 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_members.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/access_to_base_members.sol @@ -12,4 +12,4 @@ contract B is A { } // ---- // TypeError 2527: (107-110): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (157-160): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (157-160): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/array/access_to_array_push_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/array/access_to_array_push_view.sol index 3b7c19f5e..27ba16eaf 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/array/access_to_array_push_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/array/access_to_array_push_view.sol @@ -5,4 +5,4 @@ contract A { } } // ---- -// TypeError 8961: (88-96): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (88-96): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol index 000f5b009..76a05d8be 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -20,8 +20,8 @@ contract C { } } // ---- -// TypeError 8961: (52-77): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (132-153): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (201-228): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (293-323): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (414-436): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (52-77): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (132-153): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (201-228): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (293-323): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (414-436): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol index a47de539e..38762a34a 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol @@ -7,4 +7,4 @@ contract C { } // ---- // TypeError 2527: (56-59): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (130-133): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (130-133): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol index 643ba8b26..c934c9093 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol @@ -3,4 +3,4 @@ contract C { function f() public view { new D(); } } // ---- -// TypeError 8961: (58-65): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (58-65): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol index 47027331f..f0ad5efcc 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol @@ -13,6 +13,6 @@ contract C { } } // ---- -// TypeError 8961: (92-103): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (92-103): Function cannot be declared as pure because this expression (potentially) modifies the state. // TypeError 2527: (193-202): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (289-300): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (289-300): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol index be8a5aeb8..65030cb30 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol @@ -8,5 +8,5 @@ contract C { } } // ---- -// TypeError 8961: (90-109): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (180-197): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (90-109): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (180-197): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol index 774dd44e5..3b9054c41 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol @@ -12,4 +12,4 @@ contract C { } // ---- // TypeError 2527: (100-101): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (184-187): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (184-187): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol index 3c592844a..ad24e1827 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol @@ -9,4 +9,4 @@ contract C is D { } // ---- // TypeError 2527: (154-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (195-209): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (195-209): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/value_with_call_nonpayable.sol b/test/libsolidity/syntaxTests/viewPureChecker/value_with_call_nonpayable.sol index af95cbe49..cfb41d320 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/value_with_call_nonpayable.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/value_with_call_nonpayable.sol @@ -8,5 +8,5 @@ contract C { } } // ---- -// TypeError 8961: (90-111): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError 8961: (182-201): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (90-111): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (182-201): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol index d6828aac6..c3875f411 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol @@ -3,4 +3,4 @@ contract C { function f() view public { x = 2; } } // ---- -// TypeError 8961: (56-57): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError 8961: (56-57): Function cannot be declared as view because this expression (potentially) modifies the state. From 0d28b8395a01fb41d3e3e6f692f504cc29e1bacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 10 Feb 2022 16:17:51 +0100 Subject: [PATCH 05/45] storebytecode.sh: Update outdated script docstring. --- scripts/bytecodecompare/storebytecode.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh index 3574fe6bf..2192960e4 100755 --- a/scripts/bytecodecompare/storebytecode.sh +++ b/scripts/bytecodecompare/storebytecode.sh @@ -1,10 +1,12 @@ #!/usr/bin/env bash #------------------------------------------------------------------------------ -# Script used for cross-platform comparison as part of the travis automation. -# Splits all test source code into multiple files, generates bytecode and -# uploads the bytecode into github.com/ethereum/solidity-test-bytecode where -# another travis job is triggered to do the actual comparison. +# Script used for cross-platform comparison of the bytecode generated by the compiler. +# Splits all test source code into multiple files, generates bytecode and metadata +# for each file and combines it into a single report.txt file. +# +# The script is meant to be executed in CI on all supported platforms. All generated +# reports must be identical for a given compiler version. # # ------------------------------------------------------------------------------ # This file is part of solidity. From 8d0f10c2fb173118be5c4f669d5df2a8dbf5087b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 10 Feb 2022 20:44:11 +0100 Subject: [PATCH 06/45] wasm-rebuild: Incorrect comment about script location --- scripts/wasm-rebuild/docker-scripts/rebuild_current.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_current.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_current.sh index 41e554139..fbe5a9d60 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_current.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_current.sh @@ -45,7 +45,7 @@ set +e if [ -e scripts/ci/build_emscripten.sh ]; then scripts/ci/build_emscripten.sh else - # The script used to be in scripts/ci/ in earlier versions. + # The script used to be in scripts/travis-emscripten/ in earlier versions. scripts/travis-emscripten/build_emscripten.sh fi From 076bc516c8683d3804522d4ce6184add4142c846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Feb 2022 21:41:17 +0100 Subject: [PATCH 07/45] wasm-rebuild: Upgrade packages to get newer SSL certificates required to be able to download boost over HTTPS --- scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index 6293d182b..87c97095b 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -213,7 +213,9 @@ ln -sf /emsdk_portable/emscripten/bin/* /usr/local/bin rm -rf /src ln -sf /root/project /src +echo "Install dependencies and upgrade system packages." apt-get -qq update >/dev/null 2>&1 +apt-get -qq upgrade >/dev/null 2>&1 apt-get -qq install cmake >/dev/null 2>&1 echo "Create output directories." From c38cc8b73625df2b957a65fb3e768f0ff198319d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Feb 2022 21:40:18 +0100 Subject: [PATCH 08/45] wasm-rebuild: Revert solc-js changes - not needed because the script uses an old branch of solc-js --- scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index 87c97095b..36831512f 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -230,7 +230,6 @@ mkdir -p "${OUTPUTDIR}"/bin echo "Prepare solc-js." cd /root/solc-js npm install >/dev/null 2>&1 -npm run build >/dev/null 2>&1 echo "Install semver helper." npm install -g semver >/dev/null 2>&1 From dda05655b0c8866be99da0783b6cf7f9eadf2d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Feb 2022 23:01:58 +0100 Subject: [PATCH 09/45] wasm-rebuild: Patch storebytecode.sh from 0.6.1 not to use latest solc-js --- scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index 36831512f..eeeed8207 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -196,6 +196,7 @@ cp scripts/bytecodecompare/storebytecode.sh /tmp # shellcheck disable=SC2016 sed -i -e 's/rm -rf "\$TMPDIR"/cp "\$TMPDIR"\/report.txt \/tmp\/report.txt ; rm -rf "\$TMPDIR"/' /tmp/storebytecode.sh sed -i -e 's/REPO_ROOT=.*/REPO_ROOT=\/src/' /tmp/storebytecode.sh +sed -i -e 's/git clone/git clone --branch '"${SOLC_JS_BRANCH}"'/' /tmp/storebytecode.sh export SOLC_EMSCRIPTEN="On" echo "Check out solc-js repository..." From 42ac3b29b446e6c5e997185fe7137efe3cbbcee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 18 Feb 2022 14:46:25 +0100 Subject: [PATCH 10/45] wasm-rebuild: Update solc-bin URL --- scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index eeeed8207..b54c4ce02 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -27,7 +27,7 @@ done SOLIDITY_REPO_URL="https://github.com/ethereum/solidity" SOLC_JS_REPO_URL="https://github.com/ethereum/solc-js" SOLC_JS_BRANCH=wasmRebuildTests -RELEASE_URL="https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin" +RELEASE_URL="https://binaries.soliditylang.org/bin" RELEASE_COMMIT_LIST_URL="$RELEASE_URL/list.txt" SCRIPTDIR=$(dirname "$0") From 1f5407521a7980ffa77ce8ced89097987bdbf905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 18 Feb 2022 14:45:38 +0100 Subject: [PATCH 11/45] wasm-rebuild: Print tags that will be processed --- scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index b54c4ce02..9ef9caaa8 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -240,6 +240,7 @@ wget -q "${RELEASE_COMMIT_LIST_URL}" -O /tmp/release_commit_list.txt cd /src TAGS=$(git tag --list "${TAG_FILTER}" | tac) +echo "Matching tags: ${TAGS}" for TAG in ${TAGS}; do process_tag "${TAG}" done From 28340038483a887afbaea9de370eef1b7644a5a5 Mon Sep 17 00:00:00 2001 From: Abdul Karim Moro Date: Sat, 19 Feb 2022 08:31:26 +0900 Subject: [PATCH 12/45] fixed grammar on doc. If readers can gain additional pieces of information on smart contracts, then "more details" should be correct. --- docs/introduction-to-smart-contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index fa2fa34c1..94188a097 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -10,7 +10,7 @@ A Simple Smart Contract Let us begin with a basic example that sets the value of a variable and exposes it for other contracts to access. It is fine if you do not understand -everything right now, we will go into more detail later. +everything right now, we will go into more details later. Storage Example =============== From 106921c278d9b78cb894fddae350728f744aaed4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 27 Oct 2021 18:09:00 +0200 Subject: [PATCH 13/45] Extract external function part into its own function. --- libsolidity/codegen/ir/Common.cpp | 8 ++++ libsolidity/codegen/ir/Common.h | 1 + libsolidity/codegen/ir/IRGenerator.cpp | 64 ++++++++++++++++---------- libsolidity/codegen/ir/IRGenerator.h | 3 ++ 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index e75e5ef27..8f73f5733 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -41,6 +41,14 @@ YulArity YulArity::fromType(FunctionType const& _functionType) }; } +string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl) +{ + if (auto const* function = dynamic_cast(&_functionOrVarDecl)) + solAssert(!function->isConstructor()); + + return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id()); +} + string IRNames::function(FunctionDefinition const& _function) { if (_function.isConstructor()) diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 3a860f8f1..2484ad809 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -49,6 +49,7 @@ struct YulArity struct IRNames { + static std::string externalFunctionABIWrapper(Declaration const& _functionOrVardecl); static std::string function(FunctionDefinition const& _function); static std::string function(VariableDeclaration const& _varDecl); static std::string modifierInvocation(ModifierInvocation const& _modifierInvocation); diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index e361ada47..6b52010d9 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -735,6 +735,44 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) }); } +string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType) +{ + string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration()); + return m_context.functionCollector().createFunction(functionName, [&](vector&, vector&) -> string { + Whiskers t(R"X( + + let := (4, calldatasize()) + let := () + let memPos := () + let memEnd := (memPos , ) + return(memPos, sub(memEnd, memPos)) + )X"); + t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck()); + + unsigned paramVars = make_shared(_functionType.parameterTypes())->sizeOnStack(); + unsigned retVars = make_shared(_functionType.returnParameterTypes())->sizeOnStack(); + + ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); + t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); + t("params", suffixedVariableNameList("param_", 0, paramVars)); + t("retParams", suffixedVariableNameList("ret_", 0, retVars)); + + if (FunctionDefinition const* funDef = dynamic_cast(&_functionType.declaration())) + { + solAssert(!funDef->isConstructor()); + t("function", m_context.enqueueFunctionForCodeGeneration(*funDef)); + } + else if (VariableDeclaration const* varDecl = dynamic_cast(&_functionType.declaration())) + t("function", generateGetter(*varDecl)); + else + solAssert(false, "Unexpected declaration for function!"); + + t("allocateUnbounded", m_utils.allocateUnboundedFunction()); + t("abiEncode", abiFunctions.tupleEncoder(_functionType.returnParameterTypes(), _functionType.returnParameterTypes(), _contract.isLibrary())); + return t.render(); + }); +} + string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl) { IRGeneratorForStatements generator(m_context, m_utils); @@ -976,12 +1014,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) { // - - let := (4, calldatasize()) - let := () - let memPos := () - let memEnd := (memPos , ) - return(memPos, sub(memEnd, memPos)) + () } default {} @@ -1011,25 +1044,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) "() }"; } templ["delegatecallCheck"] = delegatecallCheck; - templ["callValueCheck"] = (type->isPayable() || _contract.isLibrary()) ? "" : callValueCheck(); - unsigned paramVars = make_shared(type->parameterTypes())->sizeOnStack(); - unsigned retVars = make_shared(type->returnParameterTypes())->sizeOnStack(); - - ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); - templ["abiDecode"] = abiFunctions.tupleDecoder(type->parameterTypes()); - templ["params"] = suffixedVariableNameList("param_", 0, paramVars); - templ["retParams"] = suffixedVariableNameList("ret_", 0, retVars); - - if (FunctionDefinition const* funDef = dynamic_cast(&type->declaration())) - templ["function"] = m_context.enqueueFunctionForCodeGeneration(*funDef); - else if (VariableDeclaration const* varDecl = dynamic_cast(&type->declaration())) - templ["function"] = generateGetter(*varDecl); - else - solAssert(false, "Unexpected declaration for function!"); - - templ["allocateUnbounded"] = m_utils.allocateUnboundedFunction(); - templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), _contract.isLibrary()); + templ["externalFunction"] = generateExternalFunction(_contract, *type); } t("cases", functions); FunctionDefinition const* etherReceiver = _contract.receiveFunction(); diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 126f90046..f89dc127a 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -102,6 +102,9 @@ private: /// Generates a getter for the given declaration and returns its name std::string generateGetter(VariableDeclaration const& _varDecl); + /// Generates the external part (ABI decoding and encoding) of a function or getter. + std::string generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType); + /// Generates code that assigns the initial value of the respective type. std::string generateInitialAssignment(VariableDeclaration const& _varDecl); From e9592c3f8e72bc130489a4ca291c3d36059a601e Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 15 Feb 2022 12:20:28 +0100 Subject: [PATCH 14/45] Update tests. --- .../output | 18 +- .../output | 18 +- .../output | 18 +- .../debug_info_in_yul_snippet_escaping/output | 22 +- test/cmdlineTests/exp_base_literal/output | 18 +- .../output | 62 +- test/cmdlineTests/name_simplifier/output | 4 +- test/cmdlineTests/revert_strings/output | 18 +- .../output.json | 780 ++++++++---------- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 460 ++++++----- .../output.json | 24 +- .../standard_ir_requested/output.json | 18 +- .../standard_viair_requested/output.json | 18 +- test/cmdlineTests/viair_abicoder_v1/output | 18 +- .../output | 25 +- .../yul_string_format_ascii/output.json | 18 +- .../output.json | 18 +- .../output.json | 18 +- .../yul_string_format_ascii_long/output.json | 18 +- .../yul_string_format_hex/output.json | 18 +- .../abi_encode_calldata_slice.sol | 4 +- .../struct/struct_storage_ptr.sol | 2 +- .../abi_encode_calldata_slice.sol | 4 +- .../abiEncoderV2/abi_encode_v2.sol | 2 +- ...2_in_function_inherited_in_v1_contract.sol | 2 +- .../abiEncoderV2/calldata_array.sol | 2 +- .../abiEncoderV2/storage_array_encoding.sol | 4 +- .../arrays_complex_from_and_to_storage.sol | 2 +- .../array/bytes_length_member.sol | 2 +- .../copying/array_copy_calldata_storage.sol | 2 +- .../copying/array_copy_including_array.sol | 4 +- .../array_copy_storage_storage_dyn_dyn.sol | 2 +- .../array_nested_calldata_to_storage.sol | 8 +- .../array_nested_memory_to_storage.sol | 4 +- ...on_external_storage_to_storage_dynamic.sol | 2 +- ...o_storage_dynamic_different_mutability.sol | 2 +- .../array/copying/bytes_inside_mappings.sol | 4 +- .../copy_byte_array_in_struct_to_storage.sol | 4 +- .../copy_function_internal_storage_array.sol | 2 +- .../array/copying/copy_removes_bytes_data.sol | 2 +- .../copying/copying_bytes_multiassign.sol | 2 +- .../array/dynamic_array_cleanup.sol | 2 +- .../array/dynamic_arrays_in_storage.sol | 2 +- .../array/dynamic_multi_array_cleanup.sol | 2 +- .../array/fixed_array_cleanup.sol | 2 +- .../array/fixed_arrays_in_constructors.sol | 2 +- .../array/function_array_cross_calls.sol | 2 +- .../push/array_push_struct_from_calldata.sol | 2 +- .../array/push/push_no_args_2d.sol | 4 +- .../array/push/push_no_args_bytes.sol | 2 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../copy_from_calldata_removes_bytes_data.sol | 2 +- .../constructor/arrays_in_constructors.sol | 2 +- .../bytes_in_constructors_packer.sol | 2 +- .../constructor_arguments_external.sol | 2 +- .../constructor_static_array_argument.sol | 2 +- .../constructor_inheritance_init_order.sol | 2 +- .../constructor_inheritance_init_order_2.sol | 2 +- ...ructor_with_params_diamond_inheritance.sol | 2 +- .../externalContracts/FixedFeeRegistrar.sol | 2 +- .../externalContracts/deposit_contract.sol | 10 +- .../externalContracts/prbmath_signed.sol | 2 +- .../externalContracts/prbmath_unsigned.sol | 2 +- .../externalContracts/ramanujan_pi.sol | 2 +- .../externalContracts/strings.sol | 4 +- ...ernal_call_to_nonexisting_debugstrings.sol | 2 +- .../functionCall/failed_create.sol | 4 +- .../functionCall/gas_and_value_basic.sol | 2 +- .../gas_and_value_brace_syntax.sol | 2 +- .../mapping_array_internal_argument.sol | 2 +- .../immutable/multi_creation.sol | 2 +- .../semanticTests/immutable/use_scratch.sol | 2 +- ...ted_function_calldata_memory_interface.sol | 2 +- .../inheritance/value_for_constructor.sol | 2 +- .../salted_create_with_value.sol | 2 +- .../semanticTests/smoke/constructor.sol | 2 +- .../semanticTests/state/blockhash_basic.sol | 2 +- ...ta_struct_with_nested_array_to_storage.sol | 2 +- .../conversion/recursive_storage_memory.sol | 2 +- .../copy_struct_array_from_storage.sol | 2 +- .../structs/memory_structs_nested_load.sol | 2 +- ...truct_containing_bytes_copy_and_delete.sol | 2 +- .../semanticTests/structs/struct_copy.sol | 4 +- .../struct_delete_storage_nested_small.sol | 2 +- .../struct_delete_storage_with_array.sol | 2 +- .../semanticTests/structs/structs.sol | 2 +- .../userDefinedValueType/calldata.sol | 2 +- .../userDefinedValueType/erc20.sol | 2 +- .../semanticTests/various/address_code.sol | 2 +- .../various/destructuring_assignment.sol | 2 +- .../semanticTests/various/erc20.sol | 2 +- .../skip_dynamic_types_for_structs.sol | 2 +- .../various/staticcall_for_view_and_pure.sol | 2 +- .../various/swap_in_storage_overwrite.sol | 2 +- .../viaYul/array_memory_index_access.sol | 2 +- .../viaYul/copy_struct_invalid_ir_bug.sol | 2 +- 99 files changed, 973 insertions(+), 880 deletions(-) diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output index 1b90e94a3..7775ff69c 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -108,12 +108,7 @@ object "C_6" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -150,6 +145,17 @@ object "C_6" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output index 86968e71b..35f680d92 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -108,12 +108,7 @@ object "C_6" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -150,6 +145,17 @@ object "C_6" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output index 6a87b0b46..93fad0421 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -101,12 +101,7 @@ object "C_6" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -143,6 +138,17 @@ object "C_6" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index ae3ee1735..82a74384e 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -158,12 +158,7 @@ object "D_27" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_26() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_26() } default {} @@ -238,6 +233,17 @@ object "D_27" { } + function external_fun_f_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_26() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } @@ -484,7 +490,7 @@ object "D_27" { revert(pos, returndatasize()) } mstore(add(allocate_memory_array_string(), 32), "/*") - let memPtr := allocate_memory_array_string_480() + let memPtr := allocate_memory_array_string_546() mstore(add(memPtr, 32), 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) mstore(add(memPtr, 64), shl(200, 0x2e2e2e22202a2f)) let memPos := mload(64) @@ -525,7 +531,7 @@ object "D_27" { memPtr := memPtr_1 mstore(memPtr_1, 2) } - function allocate_memory_array_string_480() -> memPtr + function allocate_memory_array_string_546() -> memPtr { let memPtr_1 := mload(64) let newFreePtr := add(memPtr_1, 96) diff --git a/test/cmdlineTests/exp_base_literal/output b/test/cmdlineTests/exp_base_literal/output index 77893da18..7b6e6e628 100644 --- a/test/cmdlineTests/exp_base_literal/output +++ b/test/cmdlineTests/exp_base_literal/output @@ -53,12 +53,7 @@ object "C_81" { { // f(uint256,uint256,uint256,uint256) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - let param_0, param_1, param_2, param_3 := abi_decode_tuple_t_uint256t_uint256t_uint256t_uint256(4, calldatasize()) - let ret_0, ret_1, ret_2, ret_3 := fun_f_80(param_0, param_1, param_2, param_3) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_uint256_t_int256_t_uint256_t_uint256__to_t_uint256_t_int256_t_uint256_t_uint256__fromStack(memPos , ret_0, ret_1, ret_2, ret_3) - return(memPos, sub(memEnd, memPos)) + external_fun_f_80() } default {} @@ -160,6 +155,17 @@ object "C_81" { } + function external_fun_f_80() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0, param_1, param_2, param_3 := abi_decode_tuple_t_uint256t_uint256t_uint256t_uint256(4, calldatasize()) + let ret_0, ret_1, ret_2, ret_3 := fun_f_80(param_0, param_1, param_2, param_3) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_uint256_t_int256_t_uint256_t_uint256__to_t_uint256_t_int256_t_uint256_t_uint256__fromStack(memPos , ret_0, ret_1, ret_2, ret_3) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/output b/test/cmdlineTests/inline_assembly_function_name_clash/output index 00192f8f4..ef16b1990 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/output +++ b/test/cmdlineTests/inline_assembly_function_name_clash/output @@ -7,157 +7,169 @@ { "abi_decode_tuple_": { - "entryPoint": 216, + "entryPoint": 122, "parameterSlots": 2, "returnSlots": 0 }, "abi_encode_t_uint256_to_t_uint256_fromStack": { - "entryPoint": 250, + "entryPoint": 156, "parameterSlots": 2, "returnSlots": 0 }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "entryPoint": 265, + "entryPoint": 171, "parameterSlots": 2, "returnSlots": 1 }, "allocate_unbounded": { - "entryPoint": 196, + "entryPoint": 102, "parameterSlots": 0, "returnSlots": 1 }, "cleanup_t_uint256": { - "entryPoint": 240, + "entryPoint": 146, "parameterSlots": 1, "returnSlots": 1 }, "convert_t_uint256_to_t_uint256": { - "entryPoint": 391, + "entryPoint": 413, "parameterSlots": 1, "returnSlots": 1 }, + "external_fun_f_25": + { + "entryPoint": 198, + "parameterSlots": 0, + "returnSlots": 0 + }, + "external_fun_g_36": + { + "entryPoint": 256, + "parameterSlots": 0, + "returnSlots": 0 + }, "fun_f_25": { - "entryPoint": 658, + "entryPoint": 680, "id": 25, "parameterSlots": 0, "returnSlots": 1 }, "fun_f_25_inner": { - "entryPoint": 624, + "entryPoint": 646, "parameterSlots": 1, "returnSlots": 1 }, "fun_g_36": { - "entryPoint": 874, + "entryPoint": 896, "id": 36, "parameterSlots": 0, "returnSlots": 1 }, "fun_g_36_inner": { - "entryPoint": 840, + "entryPoint": 862, "parameterSlots": 1, "returnSlots": 1 }, "identity": { - "entryPoint": 381, + "entryPoint": 403, "parameterSlots": 1, "returnSlots": 1 }, "modifier_m_17": { - "entryPoint": 470, + "entryPoint": 492, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, "modifier_m_19": { - "entryPoint": 547, + "entryPoint": 569, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, "modifier_m_28": { - "entryPoint": 686, + "entryPoint": 708, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, "modifier_m_30": { - "entryPoint": 763, + "entryPoint": 785, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, "prepare_store_t_uint256": { - "entryPoint": 425, + "entryPoint": 447, "parameterSlots": 1, "returnSlots": 1 }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "entryPoint": 292, + "entryPoint": 314, "parameterSlots": 0, "returnSlots": 0 }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "entryPoint": 206, + "entryPoint": 112, "parameterSlots": 0, "returnSlots": 0 }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "entryPoint": 211, + "entryPoint": 117, "parameterSlots": 0, "returnSlots": 0 }, "shift_left_0": { - "entryPoint": 302, + "entryPoint": 324, "parameterSlots": 1, "returnSlots": 1 }, "shift_right_224_unsigned": { - "entryPoint": 183, + "entryPoint": 89, "parameterSlots": 1, "returnSlots": 1 }, "update_byte_slice_32_shift_0": { - "entryPoint": 315, + "entryPoint": 337, "parameterSlots": 2, "returnSlots": 1 }, "update_storage_value_offset_0t_uint256_to_t_uint256": { - "entryPoint": 435, + "entryPoint": 457, "parameterSlots": 2, "returnSlots": 0 }, "usr$f": { - "entryPoint": 493, + "entryPoint": 515, "parameterSlots": 0, "returnSlots": 1 }, "zero_value_for_split_t_uint256": { - "entryPoint": 297, + "entryPoint": 319, "parameterSlots": 0, "returnSlots": 1 } diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 57a4cb594..3dabe9c8d 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -50,7 +50,7 @@ object "C_59" { for { } lt(src, srcEnd) { src := add(src, _2) } { if slt(sub(calldatasize(), src), _2) { revert(_1, _1) } - let value := allocate_memory_1172() + let value := allocate_memory_1307() mstore(value, calldataload(src)) mstore(dst, value) dst := add(dst, _2) @@ -68,7 +68,7 @@ object "C_59" { mstore(4, 0x41) revert(0, 0x24) } - function allocate_memory_1172() -> memPtr + function allocate_memory_1307() -> memPtr { memPtr := mload(64) let newFreePtr := add(memPtr, 32) diff --git a/test/cmdlineTests/revert_strings/output b/test/cmdlineTests/revert_strings/output index d13f9f4e5..31b3db33b 100644 --- a/test/cmdlineTests/revert_strings/output +++ b/test/cmdlineTests/revert_strings/output @@ -68,12 +68,7 @@ object "C_15" { { // f(uint256[][],uint8) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - let param_0, param_1 := abi_decode_tuple_t_array$_t_array$_t_uint256_$dyn_memory_ptr_$dyn_memory_ptrt_enum$_E_$3(4, calldatasize()) - fun_f_14(param_0, param_1) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_14() } default {} @@ -338,6 +333,17 @@ object "C_15" { } + function external_fun_f_14() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0, param_1 := abi_decode_tuple_t_array$_t_array$_t_uint256_$dyn_memory_ptr_$dyn_memory_ptrt_enum$_E_$3(4, calldatasize()) + fun_f_14(param_0, param_1) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { let start := allocate_unbounded() diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json index 1c3999afc..bb3083af9 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json @@ -78,195 +78,109 @@ stop sub_0: assembly { /* \"C\":79:428 contract C... */ mstore(0x40, 0x80) - jumpi(tag_8, iszero(lt(calldatasize, 0x04))) + jumpi(tag_7, iszero(lt(calldatasize, 0x04))) + tag_8: 0x00 dup1 revert - tag_8: + tag_7: 0x00 dup1 calldataload 0xe0 shr - dup1 + swap1 + dup2 0x26121ff0 eq - tag_10 + tag_9 jumpi + pop dup1 0x793816ec eq - tag_12 + tag_11 jumpi 0x9942ec6f eq - tag_14 + tag_13 jumpi - pop 0x00 dup1 revert - tag_14: - jumpi(tag_16, callvalue) + tag_13: + tag_8 + tag_3 + jump\t// in + tag_11: pop - tag_18 - calldatasize - tag_1 + tag_8 + tag_2 jump\t// in - tag_18: - tag_19 - /* \"C\":375:378 int */ - tag_20 - tag_6 - jump\t// in - tag_20: - /* \"C\":79:428 contract C... */ - mload(0x40) + tag_9: swap1 - dup2 - mstore - swap1 - dup2 - swap1 - 0x20 - dup3 - add - swap1 - jump - tag_19: - sub - swap1 - return - tag_16: + pop + jumpi(tag_19, callvalue) dup1 - revert - tag_12: - pop - jumpi(tag_16, callvalue) + add(calldatasize, not(0x03)) + slt tag_19 - swap1 - tag_24 - calldatasize - tag_1 - jump\t// in - tag_24: - sload - mload(0x40) - swap1 - dup2 - mstore - swap1 - dup2 - swap1 + jumpi + pop 0x20 - dup3 - add - swap1 - jump - tag_10: - pop - jumpi(tag_16, callvalue) - pop - tag_27 - calldatasize - tag_1 - jump\t// in - tag_27: - tag_19 - /* \"C\":279:298 constVar + immutVar */ - tag_20 /* \"C\":290:298 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":279:298 constVar + immutVar */ - tag_4 - jump\t// in - /* \"C\":79:428 contract C... */ - tag_1: - 0x00 - swap1 - not(0x03) - add - slt - tag_30 - jumpi - jump\t// out - tag_30: - pop - 0x00 - dup1 - revert - /* \"C\":117:119 41 */ - tag_3: - pop - mstore(0x00, shl(0xe0, 0x4e487b71)) - mstore(0x04, 0x11) - revert(0x00, 0x24) - tag_4: sub(shl(0xff, 0x01), 0x2a) + /* \"C\":117:119 41 */ dup2 sgt 0x01 and - tag_32 + tag_21 jumpi - tag_33: + /* \"C\":79:428 contract C... */ + tag_22: + mload(0x40) + /* \"C\":117:119 41 */ + swap1 0x29 add - swap1 - jump\t// out - tag_32: - tag_34 - tag_3 - jump\t// in - tag_34: - jump(tag_33) - tag_5: - 0x00 - dup2 - slt - dup1 - iszero - sub(shl(0xff, 0x01), 0x01) - dup4 - swap1 - sub - dup5 - sgt - and - tag_35 - jumpi - tag_36: - shl(0xff, 0x01) - dup3 - swap1 - sub - dup4 - slt - and - tag_37 - jumpi - add - swap1 - jump\t// out - tag_37: - tag_39 - tag_3 - jump\t// in - tag_39: - add - swap1 - jump\t// out - tag_35: - tag_40 - tag_3 - jump\t// in - tag_40: - jump(tag_36) - /* \"C\":304:341 modifier m()... */ - tag_6: /* \"C\":79:428 contract C... */ + dup2 + mstore + return + /* \"C\":117:119 41 */ + tag_21: + tag_23 + tag_4 + jump\t// in + tag_23: + jump(tag_22) + /* \"C\":79:428 contract C... */ + tag_19: + dup1 + revert + tag_2: + pop + jumpi(tag_8, callvalue) + jumpi(tag_8, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + sload(0x00) + mload(0x40) + swap1 + dup2 + mstore + return + tag_3: + pop + jumpi(tag_8, callvalue) 0x00 dup1 + add(calldatasize, not(0x03)) + slt + tag_19 + jumpi + dup1 sload /* \"C\":117:119 41 */ 0x01 @@ -275,11 +189,9 @@ sub_0: assembly { /* \"C\":79:428 contract C... */ dup2 eq - tag_41 + tag_32 jumpi - /* \"C\":304:341 modifier m()... */ - tag_42: - /* \"C\":79:428 contract C... */ + tag_33: add swap1 dup2 @@ -293,7 +205,7 @@ sub_0: assembly { 0x20 /* \"C\":403:407 this */ dup2 - /* \"C\":403:411 this.f() */ + /* \"C\":79:428 contract C... */ 0x04 /* \"C\":403:407 this */ dup2 @@ -304,38 +216,55 @@ sub_0: assembly { swap2 dup3 iszero - tag_43 + tag_34 jumpi dup1 swap3 - tag_45 + tag_36 jumpi - /* \"C\":304:341 modifier m()... */ - tag_46: + /* \"C\":79:428 contract C... */ + tag_37: /* \"C\":392:411 stateVar + this.f() */ pop pop - tag_47 - swap1 + tag_38 /* \"C\":392:422 stateVar + this.f() + immutVar */ - tag_48 + tag_39 /* \"C\":392:411 stateVar + this.f() */ - swap3 + swap2 + /* \"C\":79:428 contract C... */ + tag_40 + /* \"C\":392:411 stateVar + this.f() */ + swap4 tag_5 jump\t// in - tag_47: + tag_38: /* \"C\":414:422 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":392:422 stateVar + this.f() + immutVar */ swap1 tag_5 jump\t// in - tag_48: - /* \"C\":304:341 modifier m()... */ + tag_39: + /* \"C\":79:428 contract C... */ + mload(0x40) swap1 - jump\t// out + dup2 + mstore + swap1 + dup2 + swap1 + 0x20 + dup3 + add + swap1 + jump + tag_40: + sub + swap1 + return /* \"C\":403:411 this.f() */ - tag_45: + tag_36: /* \"C\":79:428 contract C... */ swap1 swap2 @@ -357,20 +286,21 @@ sub_0: assembly { dup4 lt or - tag_49 + tag_41 jumpi pop - swap2 - /* \"C\":403:411 this.f() */ - tag_51 - /* \"C\":392:411 stateVar + this.f() */ - tag_47 - /* \"C\":79:428 contract C... */ + tag_40 swap3 + /* \"C\":403:411 this.f() */ + tag_43 /* \"C\":392:422 stateVar + this.f() + immutVar */ - tag_48 + tag_39 /* \"C\":79:428 contract C... */ - swap5 + swap4 + /* \"C\":392:411 stateVar + this.f() */ + tag_38 + /* \"C\":79:428 contract C... */ + swap4 0x40 mstore /* \"C\":403:411 this.f() */ @@ -378,39 +308,30 @@ sub_0: assembly { dup2 add swap1 - tag_7 + tag_6 jump\t// in - tag_51: - swap2 - dup2 - swap4 + tag_43: + swap3 pop - jump(tag_46) + swap3 + jump(tag_37) /* \"C\":79:428 contract C... */ - tag_49: + tag_41: shl(0xe0, 0x4e487b71) dup2 mstore - 0x41 - /* \"C\":403:411 this.f() */ - 0x04 - /* \"C\":79:428 contract C... */ - mstore + mstore(0x04, 0x41) 0x24 - swap5 - pop - /* \"C\":117:119 41 */ - swap3 - pop - pop - pop - /* \"C\":79:428 contract C... */ - revert - /* \"C\":403:411 this.f() */ - tag_43: - /* \"C\":79:428 contract C... */ swap4 pop + swap2 + pop + pop + revert + /* \"C\":403:411 this.f() */ + tag_34: + /* \"C\":79:428 contract C... */ + swap3 pop pop pop @@ -423,25 +344,78 @@ sub_0: assembly { returndatasize swap1 revert - tag_41: - tag_52 - tag_3 + tag_32: + tag_44 + tag_4 jump\t// in - tag_52: - jump(tag_42) - tag_7: + tag_44: + jump(tag_33) + /* \"C\":117:119 41 */ + tag_4: + pop + /* \"C\":79:428 contract C... */ + shl(0xe0, 0x4e487b71) + /* \"C\":117:119 41 */ + 0x00 + mstore + mstore(0x04, 0x11) + revert(0x00, 0x24) + tag_5: + 0x00 + dup2 + slt + dup1 + iszero + sub(shl(0xff, 0x01), 0x01) + dup4 + swap1 + sub + dup5 + sgt + and + tag_45 + jumpi + tag_46: + shl(0xff, 0x01) + dup3 + swap1 + sub + dup4 + slt + and + tag_47 + jumpi + add + swap1 + jump\t// out + tag_47: + tag_49 + tag_4 + jump\t// in + tag_49: + add + swap1 + jump\t// out + tag_45: + tag_50 + tag_4 + jump\t// in + tag_50: + jump(tag_46) + /* \"C\":79:428 contract C... */ + tag_6: swap1 dup2 0x20 swap2 sub slt - tag_53 + tag_51 jumpi mload swap1 jump\t// out - tag_53: + tag_51: pop pop 0x00 @@ -571,195 +545,109 @@ stop sub_0: assembly { /* \"D\":91:166 contract D is C(3)... */ mstore(0x40, 0x80) - jumpi(tag_8, iszero(lt(calldatasize, 0x04))) + jumpi(tag_7, iszero(lt(calldatasize, 0x04))) + tag_8: 0x00 dup1 revert - tag_8: + tag_7: 0x00 dup1 calldataload 0xe0 shr - dup1 + swap1 + dup2 0x26121ff0 eq - tag_10 + tag_9 jumpi + pop dup1 0x793816ec eq - tag_12 + tag_11 jumpi 0x9942ec6f eq - tag_14 + tag_13 jumpi - pop 0x00 dup1 revert - tag_14: - jumpi(tag_16, callvalue) + tag_13: + tag_8 + tag_3 + jump\t// in + tag_11: pop - tag_18 - calldatasize - tag_1 + tag_8 + tag_2 jump\t// in - tag_18: - tag_19 - /* \"C\":375:378 int */ - tag_20 - tag_6 - jump\t// in - tag_20: - /* \"D\":91:166 contract D is C(3)... */ - mload(0x40) + tag_9: swap1 - dup2 - mstore - swap1 - dup2 - swap1 - 0x20 - dup3 - add - swap1 - jump - tag_19: - sub - swap1 - return - tag_16: + pop + jumpi(tag_19, callvalue) dup1 - revert - tag_12: - pop - jumpi(tag_16, callvalue) + add(calldatasize, not(0x03)) + slt tag_19 - swap1 - tag_24 - calldatasize - tag_1 - jump\t// in - tag_24: - sload - mload(0x40) - swap1 - dup2 - mstore - swap1 - dup2 - swap1 + jumpi + pop 0x20 - dup3 - add - swap1 - jump - tag_10: - pop - jumpi(tag_16, callvalue) - pop - tag_27 - calldatasize - tag_1 - jump\t// in - tag_27: - tag_19 - /* \"C\":279:298 constVar + immutVar */ - tag_20 /* \"C\":290:298 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":279:298 constVar + immutVar */ - tag_4 - jump\t// in - /* \"D\":91:166 contract D is C(3)... */ - tag_1: - 0x00 - swap1 - not(0x03) - add - slt - tag_30 - jumpi - jump\t// out - tag_30: - pop - 0x00 - dup1 - revert - /* \"C\":117:119 41 */ - tag_3: - pop - mstore(0x00, shl(0xe0, 0x4e487b71)) - mstore(0x04, 0x11) - revert(0x00, 0x24) - tag_4: sub(shl(0xff, 0x01), 0x2a) + /* \"C\":117:119 41 */ dup2 sgt 0x01 and - tag_32 + tag_21 jumpi - tag_33: + /* \"D\":91:166 contract D is C(3)... */ + tag_22: + mload(0x40) + /* \"C\":117:119 41 */ + swap1 0x29 add - swap1 - jump\t// out - tag_32: - tag_34 - tag_3 - jump\t// in - tag_34: - jump(tag_33) - tag_5: - 0x00 - dup2 - slt - dup1 - iszero - sub(shl(0xff, 0x01), 0x01) - dup4 - swap1 - sub - dup5 - sgt - and - tag_35 - jumpi - tag_36: - shl(0xff, 0x01) - dup3 - swap1 - sub - dup4 - slt - and - tag_37 - jumpi - add - swap1 - jump\t// out - tag_37: - tag_39 - tag_3 - jump\t// in - tag_39: - add - swap1 - jump\t// out - tag_35: - tag_40 - tag_3 - jump\t// in - tag_40: - jump(tag_36) - /* \"C\":304:341 modifier m()... */ - tag_6: /* \"D\":91:166 contract D is C(3)... */ + dup2 + mstore + return + /* \"C\":117:119 41 */ + tag_21: + tag_23 + tag_4 + jump\t// in + tag_23: + jump(tag_22) + /* \"D\":91:166 contract D is C(3)... */ + tag_19: + dup1 + revert + tag_2: + pop + jumpi(tag_8, callvalue) + jumpi(tag_8, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + sload(0x00) + mload(0x40) + swap1 + dup2 + mstore + return + tag_3: + pop + jumpi(tag_8, callvalue) 0x00 dup1 + add(calldatasize, not(0x03)) + slt + tag_19 + jumpi + dup1 sload /* \"C\":117:119 41 */ 0x01 @@ -768,11 +656,9 @@ sub_0: assembly { /* \"D\":91:166 contract D is C(3)... */ dup2 eq - tag_41 + tag_32 jumpi - /* \"C\":304:341 modifier m()... */ - tag_42: - /* \"D\":91:166 contract D is C(3)... */ + tag_33: add swap1 dup2 @@ -786,7 +672,7 @@ sub_0: assembly { 0x20 /* \"C\":403:407 this */ dup2 - /* \"C\":403:411 this.f() */ + /* \"D\":91:166 contract D is C(3)... */ 0x04 /* \"C\":403:407 this */ dup2 @@ -797,38 +683,55 @@ sub_0: assembly { swap2 dup3 iszero - tag_43 + tag_34 jumpi dup1 swap3 - tag_45 + tag_36 jumpi - /* \"C\":304:341 modifier m()... */ - tag_46: + /* \"D\":91:166 contract D is C(3)... */ + tag_37: /* \"C\":392:411 stateVar + this.f() */ pop pop - tag_47 - swap1 + tag_38 /* \"C\":392:422 stateVar + this.f() + immutVar */ - tag_48 + tag_39 /* \"C\":392:411 stateVar + this.f() */ - swap3 + swap2 + /* \"D\":91:166 contract D is C(3)... */ + tag_40 + /* \"C\":392:411 stateVar + this.f() */ + swap4 tag_5 jump\t// in - tag_47: + tag_38: /* \"C\":414:422 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":392:422 stateVar + this.f() + immutVar */ swap1 tag_5 jump\t// in - tag_48: - /* \"C\":304:341 modifier m()... */ + tag_39: + /* \"D\":91:166 contract D is C(3)... */ + mload(0x40) swap1 - jump\t// out + dup2 + mstore + swap1 + dup2 + swap1 + 0x20 + dup3 + add + swap1 + jump + tag_40: + sub + swap1 + return /* \"C\":403:411 this.f() */ - tag_45: + tag_36: /* \"D\":91:166 contract D is C(3)... */ swap1 swap2 @@ -850,20 +753,21 @@ sub_0: assembly { dup4 lt or - tag_49 + tag_41 jumpi pop - swap2 - /* \"C\":403:411 this.f() */ - tag_51 - /* \"C\":392:411 stateVar + this.f() */ - tag_47 - /* \"D\":91:166 contract D is C(3)... */ + tag_40 swap3 + /* \"C\":403:411 this.f() */ + tag_43 /* \"C\":392:422 stateVar + this.f() + immutVar */ - tag_48 + tag_39 /* \"D\":91:166 contract D is C(3)... */ - swap5 + swap4 + /* \"C\":392:411 stateVar + this.f() */ + tag_38 + /* \"D\":91:166 contract D is C(3)... */ + swap4 0x40 mstore /* \"C\":403:411 this.f() */ @@ -871,39 +775,30 @@ sub_0: assembly { dup2 add swap1 - tag_7 + tag_6 jump\t// in - tag_51: - swap2 - dup2 - swap4 + tag_43: + swap3 pop - jump(tag_46) + swap3 + jump(tag_37) /* \"D\":91:166 contract D is C(3)... */ - tag_49: + tag_41: shl(0xe0, 0x4e487b71) dup2 mstore - 0x41 - /* \"C\":403:411 this.f() */ - 0x04 - /* \"D\":91:166 contract D is C(3)... */ - mstore + mstore(0x04, 0x41) 0x24 - swap5 - pop - /* \"C\":117:119 41 */ - swap3 - pop - pop - pop - /* \"D\":91:166 contract D is C(3)... */ - revert - /* \"C\":403:411 this.f() */ - tag_43: - /* \"D\":91:166 contract D is C(3)... */ swap4 pop + swap2 + pop + pop + revert + /* \"C\":403:411 this.f() */ + tag_34: + /* \"D\":91:166 contract D is C(3)... */ + swap3 pop pop pop @@ -916,25 +811,78 @@ sub_0: assembly { returndatasize swap1 revert - tag_41: - tag_52 - tag_3 + tag_32: + tag_44 + tag_4 jump\t// in - tag_52: - jump(tag_42) - tag_7: + tag_44: + jump(tag_33) + /* \"C\":117:119 41 */ + tag_4: + pop + /* \"D\":91:166 contract D is C(3)... */ + shl(0xe0, 0x4e487b71) + /* \"C\":117:119 41 */ + 0x00 + mstore + mstore(0x04, 0x11) + revert(0x00, 0x24) + tag_5: + 0x00 + dup2 + slt + dup1 + iszero + sub(shl(0xff, 0x01), 0x01) + dup4 + swap1 + sub + dup5 + sgt + and + tag_45 + jumpi + tag_46: + shl(0xff, 0x01) + dup3 + swap1 + sub + dup4 + slt + and + tag_47 + jumpi + add + swap1 + jump\t// out + tag_47: + tag_49 + tag_4 + jump\t// in + tag_49: + add + swap1 + jump\t// out + tag_45: + tag_50 + tag_4 + jump\t// in + tag_50: + jump(tag_46) + /* \"D\":91:166 contract D is C(3)... */ + tag_6: swap1 dup2 0x20 swap2 sub slt - tag_53 + tag_51 jumpi mload swap1 jump\t// out - tag_53: + tag_51: pop pop 0x00 diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json index 1fa8928e1..16236251d 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -114,12 +114,7 @@ object \"C_6\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -156,6 +151,17 @@ object \"C_6\" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json index e427b7fe1..d017c8e9c 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -114,12 +114,7 @@ object \"C_6\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -156,6 +151,17 @@ object \"C_6\" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json index e81f461d2..afe07fad9 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -107,12 +107,7 @@ object \"C_6\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_5() } default {} @@ -149,6 +144,17 @@ object \"C_6\" { } + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 2acd68ff7..6b3c5661e 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -172,48 +172,28 @@ object \"C_54\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_30() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_30() } case 0x793816ec { // stateVar() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := getter_fun_stateVar_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_stateVar_10() } case 0x9942ec6f { // f2() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f2_53() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f2_53() } case 0xa00b982b { // constVar() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := getter_fun_constVar_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_constVar_5() } default {} @@ -260,6 +240,17 @@ object \"C_54\" { } + function external_fun_f_30() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_30() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function shift_right_unsigned_dynamic(bits, value) -> newValue { newValue := @@ -292,6 +283,28 @@ object \"C_54\" { } /// @src 0:79:435 \"contract C...\" + function external_fun_stateVar_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_stateVar_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + + function external_fun_f2_53() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f2_53() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function cleanup_t_rational_41_by_1(value) -> cleaned { cleaned := value } @@ -320,6 +333,17 @@ object \"C_54\" { } /// @src 0:79:435 \"contract C...\" + function external_fun_constVar_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_constVar_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } @@ -638,62 +662,97 @@ object \"C_54\" { switch shr(224, calldataload(_1)) case 0x26121ff0 { if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_556(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + /// @src 0:297:305 \"immutVar\" + let _2 := loadimmutable(\"8\") /// @src 0:79:435 \"contract C...\" + if and(1, sgt(_2, sub(shl(255, 1), 42))) { panic_error_0x11() } let memPos := mload(64) - return(memPos, sub(abi_encode_int256(memPos, ret), memPos)) - } - case 0x793816ec { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret_1 := sload(_1) - let memPos_1 := mload(64) - return(memPos_1, sub(abi_encode_int256(memPos_1, ret_1), memPos_1)) - } - case 0x9942ec6f { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret_2 := /** @src 0:382:385 \"int\" */ modifier_m() - /// @src 0:79:435 \"contract C...\" - let memPos_2 := mload(64) - return(memPos_2, sub(abi_encode_int256(memPos_2, ret_2), memPos_2)) - } - case 0xa00b982b { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let memPos_3 := mload(64) - return(memPos_3, sub(abi_encode_int256_555(memPos_3), memPos_3)) + mstore(memPos, add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 0:79:435 \"contract C...\" */ _2)) + return(memPos, 32) } + case 0x793816ec { external_fun_stateVar() } + case 0x9942ec6f { external_fun_f2() } + case 0xa00b982b { external_fun_constVar() } } revert(0, 0) } - function abi_decode(dataEnd) - { - if slt(add(dataEnd, not(3)), 0) { revert(0, 0) } - } - function abi_encode_int256_555(headStart) -> tail - { - tail := add(headStart, 32) - mstore(headStart, /** @src 0:124:126 \"41\" */ 0x29) - } - /// @src 0:79:435 \"contract C...\" function abi_encode_int256(headStart, value0) -> tail { tail := add(headStart, 32) mstore(headStart, value0) } + function external_fun_stateVar() + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _1 := sload(0) + let memPos := mload(64) + mstore(memPos, _1) + return(memPos, 32) + } + function external_fun_f2() + { + if callvalue() { revert(0, 0) } + let _1 := 0 + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + let _2 := sload(_1) + if eq(_2, sub(shl(255, 1), 1)) { panic_error_0x11() } + let ret := add(_2, 1) + sstore(_1, ret) + /// @src 0:410:418 \"this.f()\" + let _3 := /** @src 0:79:435 \"contract C...\" */ mload(64) + /// @src 0:410:418 \"this.f()\" + mstore(_3, /** @src 0:79:435 \"contract C...\" */ shl(228, 0x026121ff)) + /// @src 0:410:418 \"this.f()\" + let _4 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _3, /** @src 0:79:435 \"contract C...\" */ 4, /** @src 0:410:418 \"this.f()\" */ _3, 32) + if iszero(_4) + { + /// @src 0:79:435 \"contract C...\" + let pos := mload(64) + returndatacopy(pos, _1, returndatasize()) + revert(pos, returndatasize()) + } + /// @src 0:410:418 \"this.f()\" + let expr := /** @src 0:79:435 \"contract C...\" */ _1 + /// @src 0:410:418 \"this.f()\" + if _4 + { + /// @src 0:79:435 \"contract C...\" + let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 0:79:435 \"contract C...\" */ 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) + { + mstore(_1, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(_1, 0x24) + } + mstore(64, newFreePtr) + /// @src 0:410:418 \"this.f()\" + expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) + } + /// @src 0:399:418 \"stateVar + this.f()\" + let expr_1 := checked_add_int256(ret, expr) + /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" + let var := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) + /// @src 0:79:435 \"contract C...\" + let memPos := mload(64) + return(memPos, sub(abi_encode_int256(memPos, var), memPos)) + } + function external_fun_constVar() + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let memPos := mload(64) + mstore(memPos, /** @src 0:124:126 \"41\" */ 0x29) + /// @src 0:79:435 \"contract C...\" + return(memPos, 32) + } function panic_error_0x11() { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - function checked_add_int256_556(y) -> sum - { - if and(1, sgt(y, sub(shl(255, 1), 42))) { panic_error_0x11() } - sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 0:79:435 \"contract C...\" */ y) - } function checked_add_int256(x, y) -> sum { let _1 := slt(x, 0) @@ -701,51 +760,6 @@ object \"C_54\" { if and(_1, slt(y, sub(shl(255, 1), x))) { panic_error_0x11() } sum := add(x, y) } - /// @ast-id 37 @src 0:311:348 \"modifier m()...\" - function modifier_m() -> _1 - { - /// @src 0:79:435 \"contract C...\" - let _2 := 0 - let _3 := sload(_2) - if eq(_3, sub(shl(255, 1), 1)) { panic_error_0x11() } - let ret := add(_3, 1) - sstore(_2, ret) - /// @src 0:410:418 \"this.f()\" - let _4 := /** @src 0:79:435 \"contract C...\" */ mload(64) - /// @src 0:410:418 \"this.f()\" - mstore(_4, /** @src 0:79:435 \"contract C...\" */ shl(228, 0x026121ff)) - /// @src 0:410:418 \"this.f()\" - let _5 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _4, 4, _4, 32) - if iszero(_5) - { - /// @src 0:79:435 \"contract C...\" - let pos := mload(64) - returndatacopy(pos, _2, returndatasize()) - revert(pos, returndatasize()) - } - /// @src 0:410:418 \"this.f()\" - let expr := /** @src 0:79:435 \"contract C...\" */ _2 - /// @src 0:410:418 \"this.f()\" - if _5 - { - /// @src 0:79:435 \"contract C...\" - let newFreePtr := add(_4, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 0:79:435 \"contract C...\" */ 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) - { - mstore(_2, shl(224, 0x4e487b71)) - mstore(/** @src 0:410:418 \"this.f()\" */ 4, /** @src 0:79:435 \"contract C...\" */ 0x41) - revert(_2, 0x24) - } - mstore(64, newFreePtr) - /// @src 0:410:418 \"this.f()\" - expr := abi_decode_int256_fromMemory(_4, add(_4, returndatasize())) - } - /// @src 0:399:418 \"stateVar + this.f()\" - let expr_1 := checked_add_int256(ret, expr) - /// @src 0:343:344 \"_\" - _1 := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) - } - /// @src 0:79:435 \"contract C...\" function abi_decode_int256_fromMemory(headStart, dataEnd) -> value0 { if slt(sub(dataEnd, headStart), 32) { revert(0, 0) } @@ -997,48 +1011,28 @@ object \"D_72\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_30() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_30() } case 0x793816ec { // stateVar() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := getter_fun_stateVar_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_stateVar_10() } case 0x9942ec6f { // f2() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f2_53() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f2_53() } case 0xa00b982b { // constVar() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := getter_fun_constVar_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_constVar_5() } default {} @@ -1085,6 +1079,17 @@ object \"D_72\" { } + function external_fun_f_30() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_30() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function shift_right_unsigned_dynamic(bits, value) -> newValue { newValue := @@ -1117,6 +1122,28 @@ object \"D_72\" { } /// @src 1:91:166 \"contract D is C(3)...\" + function external_fun_stateVar_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_stateVar_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + + function external_fun_f2_53() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f2_53() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function cleanup_t_rational_41_by_1(value) -> cleaned { cleaned := value } @@ -1145,6 +1172,17 @@ object \"D_72\" { } /// @src 1:91:166 \"contract D is C(3)...\" + function external_fun_constVar_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_constVar_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } @@ -1471,62 +1509,97 @@ object \"D_72\" { switch shr(224, calldataload(_1)) case 0x26121ff0 { if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_556(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + /// @src 0:297:305 \"immutVar\" + let _2 := loadimmutable(\"8\") /// @src 1:91:166 \"contract D is C(3)...\" + if and(1, sgt(_2, sub(shl(255, 1), 42))) { panic_error_0x11() } let memPos := mload(64) - return(memPos, sub(abi_encode_int256(memPos, ret), memPos)) - } - case 0x793816ec { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret_1 := sload(_1) - let memPos_1 := mload(64) - return(memPos_1, sub(abi_encode_int256(memPos_1, ret_1), memPos_1)) - } - case 0x9942ec6f { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let ret_2 := /** @src 0:382:385 \"int\" */ modifier_m() - /// @src 1:91:166 \"contract D is C(3)...\" - let memPos_2 := mload(64) - return(memPos_2, sub(abi_encode_int256(memPos_2, ret_2), memPos_2)) - } - case 0xa00b982b { - if callvalue() { revert(_1, _1) } - abi_decode(calldatasize()) - let memPos_3 := mload(64) - return(memPos_3, sub(abi_encode_int256_555(memPos_3), memPos_3)) + mstore(memPos, add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 1:91:166 \"contract D is C(3)...\" */ _2)) + return(memPos, 32) } + case 0x793816ec { external_fun_stateVar() } + case 0x9942ec6f { external_fun_f2() } + case 0xa00b982b { external_fun_constVar() } } revert(0, 0) } - function abi_decode(dataEnd) - { - if slt(add(dataEnd, not(3)), 0) { revert(0, 0) } - } - function abi_encode_int256_555(headStart) -> tail - { - tail := add(headStart, 32) - mstore(headStart, /** @src 0:124:126 \"41\" */ 0x29) - } - /// @src 1:91:166 \"contract D is C(3)...\" function abi_encode_int256(headStart, value0) -> tail { tail := add(headStart, 32) mstore(headStart, value0) } + function external_fun_stateVar() + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _1 := sload(0) + let memPos := mload(64) + mstore(memPos, _1) + return(memPos, 32) + } + function external_fun_f2() + { + if callvalue() { revert(0, 0) } + let _1 := 0 + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + let _2 := sload(_1) + if eq(_2, sub(shl(255, 1), 1)) { panic_error_0x11() } + let ret := add(_2, 1) + sstore(_1, ret) + /// @src 0:410:418 \"this.f()\" + let _3 := /** @src 1:91:166 \"contract D is C(3)...\" */ mload(64) + /// @src 0:410:418 \"this.f()\" + mstore(_3, /** @src 1:91:166 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) + /// @src 0:410:418 \"this.f()\" + let _4 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _3, /** @src 1:91:166 \"contract D is C(3)...\" */ 4, /** @src 0:410:418 \"this.f()\" */ _3, 32) + if iszero(_4) + { + /// @src 1:91:166 \"contract D is C(3)...\" + let pos := mload(64) + returndatacopy(pos, _1, returndatasize()) + revert(pos, returndatasize()) + } + /// @src 0:410:418 \"this.f()\" + let expr := /** @src 1:91:166 \"contract D is C(3)...\" */ _1 + /// @src 0:410:418 \"this.f()\" + if _4 + { + /// @src 1:91:166 \"contract D is C(3)...\" + let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 1:91:166 \"contract D is C(3)...\" */ 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) + { + mstore(_1, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(_1, 0x24) + } + mstore(64, newFreePtr) + /// @src 0:410:418 \"this.f()\" + expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) + } + /// @src 0:399:418 \"stateVar + this.f()\" + let expr_1 := checked_add_int256(ret, expr) + /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" + let var := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) + /// @src 1:91:166 \"contract D is C(3)...\" + let memPos := mload(64) + return(memPos, sub(abi_encode_int256(memPos, var), memPos)) + } + function external_fun_constVar() + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let memPos := mload(64) + mstore(memPos, /** @src 0:124:126 \"41\" */ 0x29) + /// @src 1:91:166 \"contract D is C(3)...\" + return(memPos, 32) + } function panic_error_0x11() { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - function checked_add_int256_556(y) -> sum - { - if and(1, sgt(y, sub(shl(255, 1), 42))) { panic_error_0x11() } - sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 1:91:166 \"contract D is C(3)...\" */ y) - } function checked_add_int256(x, y) -> sum { let _1 := slt(x, 0) @@ -1534,51 +1607,6 @@ object \"D_72\" { if and(_1, slt(y, sub(shl(255, 1), x))) { panic_error_0x11() } sum := add(x, y) } - /// @ast-id 37 @src 0:311:348 \"modifier m()...\" - function modifier_m() -> _1 - { - /// @src 1:91:166 \"contract D is C(3)...\" - let _2 := 0 - let _3 := sload(_2) - if eq(_3, sub(shl(255, 1), 1)) { panic_error_0x11() } - let ret := add(_3, 1) - sstore(_2, ret) - /// @src 0:410:418 \"this.f()\" - let _4 := /** @src 1:91:166 \"contract D is C(3)...\" */ mload(64) - /// @src 0:410:418 \"this.f()\" - mstore(_4, /** @src 1:91:166 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) - /// @src 0:410:418 \"this.f()\" - let _5 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _4, 4, _4, 32) - if iszero(_5) - { - /// @src 1:91:166 \"contract D is C(3)...\" - let pos := mload(64) - returndatacopy(pos, _2, returndatasize()) - revert(pos, returndatasize()) - } - /// @src 0:410:418 \"this.f()\" - let expr := /** @src 1:91:166 \"contract D is C(3)...\" */ _2 - /// @src 0:410:418 \"this.f()\" - if _5 - { - /// @src 1:91:166 \"contract D is C(3)...\" - let newFreePtr := add(_4, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 1:91:166 \"contract D is C(3)...\" */ 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) - { - mstore(_2, shl(224, 0x4e487b71)) - mstore(/** @src 0:410:418 \"this.f()\" */ 4, /** @src 1:91:166 \"contract D is C(3)...\" */ 0x41) - revert(_2, 0x24) - } - mstore(64, newFreePtr) - /// @src 0:410:418 \"this.f()\" - expr := abi_decode_int256_fromMemory(_4, add(_4, returndatasize())) - } - /// @src 0:399:418 \"stateVar + this.f()\" - let expr_1 := checked_add_int256(ret, expr) - /// @src 0:343:344 \"_\" - _1 := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) - } - /// @src 1:91:166 \"contract D is C(3)...\" function abi_decode_int256_fromMemory(headStart, dataEnd) -> value0 { if slt(sub(dataEnd, headStart), 32) { revert(0, 0) } diff --git a/test/cmdlineTests/standard_irOptimized_requested/output.json b/test/cmdlineTests/standard_irOptimized_requested/output.json index c56849339..85b861602 100644 --- a/test/cmdlineTests/standard_irOptimized_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_requested/output.json @@ -34,17 +34,7 @@ object \"C_7\" { { let selector := shift_right_224_unsigned(calldataload(0)) switch selector - case 0x26121ff0 { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode_tuple_(4, calldatasize()) - fun_f_6() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos) - return(memPos, sub(memEnd, memPos)) - } + case 0x26121ff0 { external_fun_f_6() } default { } } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() @@ -65,6 +55,18 @@ object \"C_7\" { } function abi_encode_tuple__to__fromStack(headStart) -> tail { tail := add(headStart, 0) } + function external_fun_f_6() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode_tuple_(4, calldatasize()) + fun_f_6() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos) + return(memPos, sub(memEnd, memPos)) + } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } /// @ast-id 6 @src 0:92:119 \"function f() public pure {}\" diff --git a/test/cmdlineTests/standard_ir_requested/output.json b/test/cmdlineTests/standard_ir_requested/output.json index 59f07f768..1e7f8dec3 100644 --- a/test/cmdlineTests/standard_ir_requested/output.json +++ b/test/cmdlineTests/standard_ir_requested/output.json @@ -52,12 +52,7 @@ object \"C_7\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_6() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_6() } default {} @@ -94,6 +89,17 @@ object \"C_7\" { } + function external_fun_f_6() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_6() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index b72923f48..881a4bad4 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -121,12 +121,7 @@ object \"D_16\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_15() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) + external_fun_f_15() } default {} @@ -163,6 +158,17 @@ object \"D_16\" { } + function external_fun_f_15() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_15() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/viair_abicoder_v1/output b/test/cmdlineTests/viair_abicoder_v1/output index cedda56dc..c71c535da 100644 --- a/test/cmdlineTests/viair_abicoder_v1/output +++ b/test/cmdlineTests/viair_abicoder_v1/output @@ -53,12 +53,7 @@ object "test_11" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_bool__to_t_bool__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -105,6 +100,17 @@ object "test_11" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_bool__to_t_bool__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output index cc67ca5bc..5b7c3fdb0 100644 --- a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output @@ -125,18 +125,7 @@ object "C_6" { if iszero(lt(calldatasize(), 4)) { let selector := shift_right_unsigned(calldataload(0)) - if eq(0x26121ff0, selector) - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - fun_f() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } + if eq(0x26121ff0, selector) { external_fun_f() } } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } @@ -421,6 +410,18 @@ object "C_6" { let tail_86 := tail_1 tail := tail_1 } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + fun_f() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } /// @ast-id 5 @src 0:74:101 "function f() public pure {}" diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index 2354929e4..46dd577eb 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -52,12 +52,7 @@ object \"C_11\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -132,6 +127,17 @@ object \"C_11\" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json index 84e9ff271..0ffffa3a4 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json @@ -52,12 +52,7 @@ object \"C_11\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_bytes32__to_t_bytes32__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -104,6 +99,17 @@ object \"C_11\" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_bytes32__to_t_bytes32__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index 716a1cc6e..1fb107015 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -52,12 +52,7 @@ object \"C_11\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -104,6 +99,17 @@ object \"C_11\" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 1f52e103b..bf757e685 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -52,12 +52,7 @@ object \"C_11\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -132,6 +127,17 @@ object \"C_11\" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index 04166a760..0ff492ce4 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -52,12 +52,7 @@ object \"C_11\" { { // f() - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - let ret_0 := fun_f_10() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos , ret_0) - return(memPos, sub(memEnd, memPos)) + external_fun_f_10() } default {} @@ -104,6 +99,17 @@ object \"C_11\" { } + function external_fun_f_10() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index e54c39d32..64ca83041 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -60,10 +60,10 @@ contract C { // compileViaYul: also // ---- // test_bytes() -> -// gas irOptimized: 373483 +// gas irOptimized: 371847 // gas legacy: 418955 // gas legacyOptimized: 326783 // test_uint256() -> -// gas irOptimized: 524664 +// gas irOptimized: 522929 // gas legacy: 586784 // gas legacyOptimized: 451529 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index 19d9b1b9a..3c1ffa6cf 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -26,6 +26,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 167446 +// gas irOptimized: 167672 // gas legacy: 169347 // gas legacyOptimized: 167269 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index 53aeb8949..1c4e8d7a2 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -61,10 +61,10 @@ contract C { // compileViaYul: also // ---- // test_bytes() -> -// gas irOptimized: 373483 +// gas irOptimized: 371847 // gas legacy: 418955 // gas legacyOptimized: 326783 // test_uint256() -> -// gas irOptimized: 524664 +// gas irOptimized: 522929 // gas legacy: 586784 // gas legacyOptimized: 451529 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index 3e9697698..82ece5f3f 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -53,6 +53,6 @@ contract C { // f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 -// gas irOptimized: 113361 +// gas irOptimized: 113299 // gas legacy: 114900 // gas legacyOptimized: 112606 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol index 953fa7945..2aa7a251b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol @@ -32,6 +32,6 @@ contract C is B { // compileViaYul: also // ---- // test() -> 77 -// gas irOptimized: 119931 +// gas irOptimized: 119895 // gas legacy: 155093 // gas legacyOptimized: 111550 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index 11fccbb61..8d1f1a727 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -21,6 +21,6 @@ contract C { // f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true -// gas irOptimized: 171964 +// gas irOptimized: 171838 // gas legacy: 141644 // gas legacyOptimized: 121532 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 1f836bfaf..1f1e97720 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -19,10 +19,10 @@ contract C { // compileViaYul: also // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180925 +// gas irOptimized: 180931 // gas legacy: 184929 // gas legacyOptimized: 181504 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 -// gas irOptimized: 112535 +// gas irOptimized: 112539 // gas legacy: 115468 // gas legacyOptimized: 112988 diff --git a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol index e8d567059..7a2a06a2e 100644 --- a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol @@ -14,7 +14,7 @@ contract Test { // compileViaYul: also // ---- // set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06 -// gas irOptimized: 189910 +// gas irOptimized: 189871 // gas legacy: 211149 // gas legacyOptimized: 206054 // data(uint256,uint256): 0x02, 0x02 -> 0x09 diff --git a/test/libsolidity/semanticTests/array/bytes_length_member.sol b/test/libsolidity/semanticTests/array/bytes_length_member.sol index bb4e21e16..aaf990ef6 100644 --- a/test/libsolidity/semanticTests/array/bytes_length_member.sol +++ b/test/libsolidity/semanticTests/array/bytes_length_member.sol @@ -15,7 +15,7 @@ contract c { // ---- // getLength() -> 0 // set(): 1, 2 -> true -// gas irOptimized: 110433 +// gas irOptimized: 110439 // gas legacy: 110726 // gas legacyOptimized: 110567 // getLength() -> 68 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol index 2a401cd87..6c876286b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -22,7 +22,7 @@ contract c { // compileViaYul: also // ---- // store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 -// gas irOptimized: 650669 +// gas irOptimized: 650647 // gas legacy: 694515 // gas legacyOptimized: 694013 // retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index 4f7023250..1c030deba 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -37,12 +37,12 @@ contract c { // compileViaYul: also // ---- // test() -> 0x02000202 -// gas irOptimized: 4652092 +// gas irOptimized: 4652058 // gas legacy: 4578341 // gas legacyOptimized: 4548354 // storageEmpty -> 1 // clear() -> 0, 0 -// gas irOptimized: 4483169 +// gas irOptimized: 4483175 // gas legacy: 4410769 // gas legacyOptimized: 4382531 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol index 202b3ad26..b4b392974 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol @@ -17,7 +17,7 @@ contract c { // ---- // setData1(uint256,uint256,uint256): 10, 5, 4 -> // copyStorageStorage() -> -// gas irOptimized: 111426 +// gas irOptimized: 111406 // gas legacy: 109278 // gas legacyOptimized: 109268 // getData2(uint256): 5 -> 10, 4 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol index 3cc9c9bd9..f3f3e8236 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol @@ -38,10 +38,10 @@ contract c { // compileViaYul: true // ---- // test1(uint256[][]): 0x20, 2, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 181308 +// gas irOptimized: 181298 // test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 157901 +// gas irOptimized: 157936 // test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65 -// gas irOptimized: 135108 +// gas irOptimized: 135098 // test4(uint256[2][2]): 23, 42, 23, 42 -> 65 -// gas irOptimized: 111428 +// gas irOptimized: 111362 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol index 826d48b2b..e8b460b4f 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol @@ -40,12 +40,12 @@ contract Test { // compileViaYul: also // ---- // test() -> 24 -// gas irOptimized: 227167 +// gas irOptimized: 227133 // gas legacy: 227133 // gas legacyOptimized: 226547 // test1() -> 3 // test2() -> 6 // test3() -> 24 -// gas irOptimized: 133621 +// gas irOptimized: 133597 // gas legacy: 134295 // gas legacyOptimized: 133383 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol index 8bd9ee42c..d872534cd 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -47,7 +47,7 @@ contract C { // compileViaYul: also // ---- // copyExternalStorageArrayOfFunctionType() -> true -// gas irOptimized: 104701 +// gas irOptimized: 104669 // gas legacy: 108725 // gas legacyOptimized: 102441 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol index 63236ed77..71399a281 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -50,7 +50,7 @@ contract C { // compileViaYul: also // ---- // copyExternalStorageArraysOfFunctionType() -> true -// gas irOptimized: 104372 +// gas irOptimized: 104342 // gas legacy: 108462 // gas legacyOptimized: 102174 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol index 809ef247d..ae2698551 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol @@ -7,11 +7,11 @@ contract c { // compileViaYul: also // ---- // set(uint256): 1, 2 -> true -// gas irOptimized: 110699 +// gas irOptimized: 110604 // gas legacy: 111091 // gas legacyOptimized: 110736 // set(uint256): 2, 2, 3, 4, 5 -> true -// gas irOptimized: 177659 +// gas irOptimized: 177564 // gas legacy: 178021 // gas legacyOptimized: 177666 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index ed0fe8f5f..72a837d1b 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -37,11 +37,11 @@ contract C { // compileViaYul: also // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 179952 +// gas irOptimized: 179899 // gas legacy: 180694 // gas legacyOptimized: 180088 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 107332 +// gas irOptimized: 107274 // gas legacy: 107895 // gas legacyOptimized: 107254 // h() -> 0x40, 0x60, 0x00, 0x00 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol index 6f019c77c..7550a9225 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol @@ -18,6 +18,6 @@ contract C { // compileViaYul: also // ---- // test() -> 7 -// gas irOptimized: 124080 +// gas irOptimized: 124041 // gas legacy: 205196 // gas legacyOptimized: 204987 diff --git a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol index b8ec0d97f..8d8bd4d50 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol @@ -9,7 +9,7 @@ contract c { // compileViaYul: also // ---- // set(): 1, 2, 3, 4, 5 -> true -// gas irOptimized: 177417 +// gas irOptimized: 177390 // gas legacy: 177656 // gas legacyOptimized: 177496 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol index 3583a752d..7b2af9607 100644 --- a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol +++ b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol @@ -21,7 +21,7 @@ contract sender { // compileViaYul: also // ---- // (): 7 -> -// gas irOptimized: 110941 +// gas irOptimized: 110954 // gas legacy: 111082 // gas legacyOptimized: 111027 // val() -> 0 diff --git a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol index 9f4be2119..019a3fca0 100644 --- a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol @@ -16,7 +16,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> -// gas irOptimized: 519848 +// gas irOptimized: 519886 // gas legacy: 521773 // gas legacyOptimized: 517048 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index 2587442d5..4ed8c050b 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -44,7 +44,7 @@ contract c { // ---- // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> -// gas irOptimized: 104355 +// gas irOptimized: 111304 // gas legacy: 108571 // gas legacyOptimized: 100417 // getLengths() -> 48, 49 diff --git a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol index 6aecbde32..cf310f86d 100644 --- a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol @@ -18,7 +18,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> 8 -// gas irOptimized: 122528 +// gas irOptimized: 122534 // gas legacy: 121756 // gas legacyOptimized: 120687 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index dd131f287..b09cb5812 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -13,7 +13,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> -// gas irOptimized: 465585 +// gas irOptimized: 465544 // gas legacy: 471460 // gas legacyOptimized: 467520 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index ddead0503..07a054514 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -11,7 +11,7 @@ contract Creator { // compileViaYul: also // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 132278 +// gas irOptimized: 129908 // gas legacy: 176789 // gas legacyOptimized: 129585 // r() -> 4 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index 9c78c1207..e9aef6d0d 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -45,6 +45,6 @@ contract C { // compileViaYul: also // ---- // test() -> 5, 6, 7 -// gas irOptimized: 290947 +// gas irOptimized: 290567 // gas legacy: 452172 // gas legacyOptimized: 285017 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol index f6da6a398..7546a664b 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol @@ -18,6 +18,6 @@ contract c { // compileViaYul: also // ---- // test((uint16,uint16,uint16[3],uint16[])): 0x20, 2, 3, 0, 0, 4, 0xC0, 4, 0, 0, 5, 0, 0 -> 2, 3, 4, 5 -// gas irOptimized: 138785 +// gas irOptimized: 138732 // gas legacy: 145150 // gas legacyOptimized: 139171 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol index 8df809acd..761bf3ee3 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol @@ -29,14 +29,14 @@ contract C { // ---- // l() -> 0 // f(uint256,uint256): 42, 64 -> -// gas irOptimized: 112555 +// gas irOptimized: 112528 // gas legacy: 108234 // gas legacyOptimized: 102245 // l() -> 1 // ll(uint256): 0 -> 43 // a(uint256,uint256): 0, 42 -> 64 // f(uint256,uint256): 84, 128 -> -// gas irOptimized: 116427 +// gas irOptimized: 116400 // gas legacy: 107780 // gas legacyOptimized: 96331 // l() -> 2 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol index defbf4149..830f25b02 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol @@ -23,7 +23,7 @@ contract C { // ---- // l() -> 0 // g(uint256): 70 -> -// gas irOptimized: 184507 +// gas irOptimized: 185936 // gas legacy: 184991 // gas legacyOptimized: 180608 // l() -> 70 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index ee1a57b1e..87280f6a4 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -26,6 +26,6 @@ contract Main { // compileViaYul: also // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 113581 +// gas irOptimized: 113552 // gas legacy: 126596 // gas legacyOptimized: 113823 diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol index 87067b77b..7773c6832 100644 --- a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol @@ -11,7 +11,7 @@ contract c { // compileViaYul: also // ---- // (): 1, 2, 3, 4, 5 -> -// gas irOptimized: 155178 +// gas irOptimized: 155181 // gas legacy: 155254 // gas legacyOptimized: 155217 // checkIfDataIsEmpty() -> false diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 7885b24a3..759c58d30 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 456668 +// gas irOptimized: 443921 // gas legacy: 590683 // gas legacyOptimized: 448326 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 434b926fc..7210ac269 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 308497 +// gas irOptimized: 300765 // gas legacy: 428917 // gas legacyOptimized: 298128 diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index 6ee258bd6..2206fd351 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -19,7 +19,7 @@ contract Main { // compileViaYul: also // ---- // constructor(): "abc", true -// gas irOptimized: 112563 +// gas irOptimized: 107175 // gas legacy: 145838 // gas legacyOptimized: 104017 // getFlag() -> true diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index ab90a0bb9..f6fab1092 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -12,7 +12,7 @@ contract C { // compileViaYul: also // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 180731 +// gas irOptimized: 174905 // gas legacy: 221377 // gas legacyOptimized: 177671 // a() -> 1 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index 41a050fc4..2518deb92 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -15,5 +15,5 @@ contract B is A { // compileViaYul: true // ---- // constructor() -> -// gas irOptimized: 122233 +// gas irOptimized: 122017 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index db58499ea..68506528b 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -12,7 +12,7 @@ contract B is A { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 122233 +// gas irOptimized: 122017 // gas legacy: 135046 // gas legacyOptimized: 116176 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol index fe3c95b54..8f891116e 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -23,7 +23,7 @@ contract D is B, C { // compileViaYul: also // ---- // constructor(): 2, 0 -> -// gas irOptimized: 159542 +// gas irOptimized: 160166 // gas legacy: 170665 // gas legacyOptimized: 145396 // i() -> 2 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index fc0b416fd..e6d6c478b 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -76,7 +76,7 @@ contract FixedFeeRegistrar is Registrar { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 426283 +// gas irOptimized: 413485 // gas legacy: 936897 // gas legacyOptimized: 490983 // reserve(string), 69 ether: 0x20, 3, "abc" -> diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 7f5799805..d98e73792 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -178,7 +178,7 @@ contract DepositContract is IDepositContract, ERC165 { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1557137 +// gas irOptimized: 1543359 // gas legacy: 2436584 // gas legacyOptimized: 1776483 // supportsInterface(bytes4): 0x0 -> 0 @@ -186,27 +186,27 @@ contract DepositContract is IDepositContract, ERC165 { // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 122169 +// gas irOptimized: 122135 // gas legacy: 150465 // gas legacyOptimized: 122798 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 122169 +// gas irOptimized: 122135 // gas legacy: 150465 // gas legacyOptimized: 122798 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 122148 +// gas irOptimized: 122114 // gas legacy: 150475 // gas legacyOptimized: 122811 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 122148 +// gas irOptimized: 122114 // gas legacy: 150475 // gas legacyOptimized: 122811 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 9de7a30d8..56abe4a9d 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -50,7 +50,7 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1924392 +// gas irOptimized: 1938339 // gas legacy: 2480887 // gas legacyOptimized: 1874490 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 11001fffa..720f57489 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -50,7 +50,7 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1778342 +// gas irOptimized: 1790188 // gas legacy: 2250130 // gas legacyOptimized: 1746528 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 763a8acda..45976217b 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -35,7 +35,7 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 465357 +// gas irOptimized: 465789 // gas legacy: 672749 // gas legacyOptimized: 479606 // prb_pi() -> 3141592656369545286 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 7c4028bb9..a16f884e8 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -51,7 +51,7 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 702619 +// gas irOptimized: 707330 // gas legacy: 1130761 // gas legacyOptimized: 750416 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 @@ -71,6 +71,6 @@ contract test { // gas legacy: 31621 // gas legacyOptimized: 27914 // benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020 -// gas irOptimized: 2040067 +// gas irOptimized: 2040045 // gas legacy: 4381235 // gas legacyOptimized: 2317529 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index 26faf248f..ce8d29b8b 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -27,7 +27,7 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 448383 +// gas irOptimized: 445767 // gas legacy: 834272 // gas legacyOptimized: 510004 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 54cd9f06a..4862f3b4c 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -18,7 +18,7 @@ contract C { // compileViaYul: also // ---- // constructor(), 20 wei -// gas irOptimized: 218775 +// gas irOptimized: 213663 // gas legacy: 294569 // gas legacyOptimized: 174699 // f(uint256): 20 -> 1370859564726510389319704988634906228201275401179 @@ -26,7 +26,7 @@ contract C { // f(uint256): 20 -> FAILURE // x() -> 1 // stack(uint256): 1023 -> FAILURE -// gas irOptimized: 296769 +// gas irOptimized: 304303 // gas legacy: 483942 // gas legacyOptimized: 298807 // x() -> 1 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index b1d9299d8..a4c3fb3dd 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -41,7 +41,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 285350 +// gas irOptimized: 274154 // gas legacy: 402654 // gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 9e2491ac1..5b39dda48 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -40,7 +40,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 285350 +// gas irOptimized: 274154 // gas legacy: 402654 // gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol index d3e2ba075..f1e2f1116 100644 --- a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol +++ b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol @@ -20,7 +20,7 @@ contract test { // compileViaYul: also // ---- // set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0 -// gas irOptimized: 111896 +// gas irOptimized: 111929 // gas legacy: 113806 // gas legacyOptimized: 111781 // get(uint8): 1 -> 21, 22, 42, 43 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index 2f74c17f5..840a8761b 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -29,7 +29,7 @@ contract C { // compileViaYul: also // ---- // f() -> 3, 7, 5 -// gas irOptimized: 127387 +// gas irOptimized: 127302 // gas legacy: 151334 // gas legacyOptimized: 125166 // x() -> 7 diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index 4fb3bf245..e065f3f01 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -17,7 +17,7 @@ contract C { // compileViaYul: also // ---- // constructor(): 3 -> -// gas irOptimized: 137184 +// gas irOptimized: 131042 // gas legacy: 209361 // gas legacyOptimized: 139324 // f() -> 84, 23 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 46992694e..8f3584a9d 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -25,6 +25,6 @@ contract B { // compileViaYul: also // ---- // g() -> 42 -// gas irOptimized: 111781 +// gas irOptimized: 111770 // gas legacy: 185053 // gas legacyOptimized: 114598 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index b2f0f8a6b..94cd46a2d 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -42,7 +42,7 @@ contract Main { // compileViaYul: also // ---- // constructor(), 22 wei -> -// gas irOptimized: 288778 +// gas irOptimized: 276469 // gas legacy: 402045 // gas legacyOptimized: 266772 // getFlag() -> true diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index e8fe01687..af9c7e76b 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -22,6 +22,6 @@ contract A { // compileViaYul: also // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 272947 +// gas irOptimized: 272338 // gas legacy: 422501 // gas legacyOptimized: 287472 diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 7667c2443..a6e812e9a 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -14,7 +14,7 @@ contract C { // compileViaYul: also // ---- // constructor(), 2 wei: 3 -> -// gas irOptimized: 111723 +// gas irOptimized: 111699 // gas legacy: 151416 // gas legacyOptimized: 108388 // state() -> 3 diff --git a/test/libsolidity/semanticTests/state/blockhash_basic.sol b/test/libsolidity/semanticTests/state/blockhash_basic.sol index d4dbffcb8..9abeb90aa 100644 --- a/test/libsolidity/semanticTests/state/blockhash_basic.sol +++ b/test/libsolidity/semanticTests/state/blockhash_basic.sol @@ -14,7 +14,7 @@ contract C { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 119839 +// gas irOptimized: 115297 // gas legacy: 155081 // gas legacyOptimized: 107997 // genesisHash() -> 0x3737373737373737373737373737373737373737373737373737373737373737 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol index 7b84033d8..6e65cd239 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol @@ -18,6 +18,6 @@ contract C { // compileViaYul: also // ---- // f(uint32,(uint128,uint256[][2],uint32)): 55, 0x40, 77, 0x60, 88, 0x40, 0x40, 2, 1, 2 -> 55, 77, 1, 2, 88 -// gas irOptimized: 203397 +// gas irOptimized: 203312 // gas legacy: 209194 // gas legacyOptimized: 203583 diff --git a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol index 0d0aba8c8..c23a15ec0 100644 --- a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol +++ b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol @@ -25,6 +25,6 @@ contract CopyTest { // compileViaYul: also // ---- // run() -> 2, 23, 42 -// gas irOptimized: 193980 +// gas irOptimized: 194005 // gas legacy: 186016 // gas legacyOptimized: 184668 diff --git a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol index 7bbe495ce..258ff350b 100644 --- a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol +++ b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol @@ -88,7 +88,7 @@ contract Test { // compileViaYul: also // ---- // test1() -> true -// gas irOptimized: 150618 +// gas irOptimized: 150545 // gas legacy: 150266 // gas legacyOptimized: 149875 // test2() -> true diff --git a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol index 12ec4ca18..5dd4d48a6 100644 --- a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol +++ b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol @@ -69,7 +69,7 @@ contract Test { // compileViaYul: also // ---- // load() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 -// gas irOptimized: 111179 +// gas irOptimized: 111432 // gas legacy: 112999 // gas legacyOptimized: 110881 // store() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 diff --git a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol index a677b5be8..6b5d1f022 100644 --- a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol +++ b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol @@ -25,7 +25,7 @@ contract c { // ---- // storageEmpty -> 1 // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 133752 +// gas irOptimized: 133728 // gas legacy: 134436 // gas legacyOptimized: 133879 // test(uint256): 32 -> "3" diff --git a/test/libsolidity/semanticTests/structs/struct_copy.sol b/test/libsolidity/semanticTests/structs/struct_copy.sol index f170dca3f..03a063bb8 100644 --- a/test/libsolidity/semanticTests/structs/struct_copy.sol +++ b/test/libsolidity/semanticTests/structs/struct_copy.sol @@ -38,12 +38,12 @@ contract c { // compileViaYul: also // ---- // set(uint256): 7 -> true -// gas irOptimized: 110119 +// gas irOptimized: 110051 // gas legacy: 110616 // gas legacyOptimized: 110006 // retrieve(uint256): 7 -> 1, 3, 4, 2 // copy(uint256,uint256): 7, 8 -> true -// gas irOptimized: 118698 +// gas irOptimized: 118597 // gas legacy: 119166 // gas legacyOptimized: 118622 // retrieve(uint256): 7 -> 1, 3, 4, 2 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol index bc18d3192..ded05d8d6 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol @@ -33,4 +33,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0, 0, 0 -// gas irOptimized: 117289 +// gas irOptimized: 117403 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index e759520b4..44acf38e4 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -44,7 +44,7 @@ contract C { // compileViaYul: also // ---- // f() -> -// gas irOptimized: 121618 +// gas irOptimized: 121624 // gas legacy: 122132 // gas legacyOptimized: 121500 // g() -> diff --git a/test/libsolidity/semanticTests/structs/structs.sol b/test/libsolidity/semanticTests/structs/structs.sol index b56a2ec22..3356eac16 100644 --- a/test/libsolidity/semanticTests/structs/structs.sol +++ b/test/libsolidity/semanticTests/structs/structs.sol @@ -32,7 +32,7 @@ contract test { // ---- // check() -> false // set() -> -// gas irOptimized: 134335 +// gas irOptimized: 134432 // gas legacy: 135277 // gas legacyOptimized: 134064 // check() -> true diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index 1927b2519..bd7e2fe9c 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -51,7 +51,7 @@ contract C { // compileViaYul: also // ---- // test_f() -> true -// gas irOptimized: 122509 +// gas irOptimized: 122413 // gas legacy: 126168 // gas legacyOptimized: 123199 // test_g() -> true diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 220d9d9a2..c2c5f3cdc 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -115,7 +115,7 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 447831 +// gas irOptimized: 423885 // gas legacy: 861559 // gas legacyOptimized: 420959 // totalSupply() -> 20 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 6072d5ac3..38e0fb13f 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -17,7 +17,7 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 199687 +// gas irOptimized: 199723 // gas legacy: 241124 // gas legacyOptimized: 155549 // initCode() -> 0x20, 0 diff --git a/test/libsolidity/semanticTests/various/destructuring_assignment.sol b/test/libsolidity/semanticTests/various/destructuring_assignment.sol index ee6f7690d..cc93152ea 100644 --- a/test/libsolidity/semanticTests/various/destructuring_assignment.sol +++ b/test/libsolidity/semanticTests/various/destructuring_assignment.sol @@ -36,6 +36,6 @@ contract C { // compileViaYul: also // ---- // f(bytes): 0x20, 0x5, "abcde" -> 0 -// gas irOptimized: 240685 +// gas irOptimized: 240691 // gas legacy: 240358 // gas legacyOptimized: 239682 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index 64a3286a9..9ba4e3cb7 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -98,7 +98,7 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 443295 +// gas irOptimized: 419330 // gas legacy: 833310 // gas legacyOptimized: 416135 // totalSupply() -> 20 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index cad181c8f..ba4e7426a 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -22,6 +22,6 @@ contract C { // compileViaYul: also // ---- // g() -> 2, 6 -// gas irOptimized: 178835 +// gas irOptimized: 178822 // gas legacy: 180762 // gas legacyOptimized: 179481 diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol index 1950f7a4d..06faab882 100644 --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol @@ -42,6 +42,6 @@ contract D { // gas legacy: 98438801 // gas legacyOptimized: 98438594 // fpure() -> FAILURE -// gas irOptimized: 98438626 +// gas irOptimized: 98438625 // gas legacy: 98438801 // gas legacyOptimized: 98438595 diff --git a/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol b/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol index c8398b2bf..9b7a4306f 100644 --- a/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol +++ b/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol @@ -30,7 +30,7 @@ contract c { // x() -> 0, 0 // y() -> 0, 0 // set() -> -// gas irOptimized: 109733 +// gas irOptimized: 109713 // gas legacy: 109732 // gas legacyOptimized: 109682 // x() -> 1, 2 diff --git a/test/libsolidity/semanticTests/viaYul/array_memory_index_access.sol b/test/libsolidity/semanticTests/viaYul/array_memory_index_access.sol index b603fb786..6ef403dcc 100644 --- a/test/libsolidity/semanticTests/viaYul/array_memory_index_access.sol +++ b/test/libsolidity/semanticTests/viaYul/array_memory_index_access.sol @@ -28,7 +28,7 @@ contract C { // index(uint256): 10 -> true // index(uint256): 20 -> true // index(uint256): 0xFF -> true -// gas irOptimized: 138441 +// gas irOptimized: 138410 // gas legacy: 248854 // gas legacyOptimized: 152638 // accessIndex(uint256,int256): 10, 1 -> 2 diff --git a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol index 70e3a34d4..497dd36c8 100644 --- a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol +++ b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol @@ -23,6 +23,6 @@ contract C { // compileViaYul: also // ---- // f() -> -// gas irOptimized: 113142 +// gas irOptimized: 113096 // gas legacy: 112937 // gas legacyOptimized: 112608 From 195f72e844e7cac0907053f6f5a8cd5857bafc23 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Thu, 10 Feb 2022 19:44:08 +0530 Subject: [PATCH 15/45] Added errorSelector field for custom errors --- Changelog.md | 3 +- libsolidity/ast/ASTJsonConverter.cpp | 21 ++++- test/libsolidity/ASTJSON/documentation.json | 1 + .../libsolidity/ASTJSON/event_definition.json | 1 + ...vent_with_variables_of_internal_types.json | 0 ...event_with_variables_of_internal_types.sol | 5 ++ ...variables_of_internal_types_parseOnly.json | 78 +++++++++++++++++++ test/libsolidity/ASTJSON/used_errors.json | 20 ++--- test/libsolidity/ASTJSON/used_errors.sol | 2 +- .../ASTJSON/used_errors_parseOnly.json | 18 ++--- 10 files changed, 124 insertions(+), 25 deletions(-) create mode 100644 test/libsolidity/ASTJSON/event_with_variables_of_internal_types.json create mode 100644 test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol create mode 100644 test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json diff --git a/Changelog.md b/Changelog.md index 300bc0122..fd7dda584 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,12 +4,11 @@ Language Features: Compiler Features: - +* JSON-AST: Added selector field for errors and events. Bugfixes: - ### 0.8.12 (2022-02-16) Language Features: diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 326cca43e..97417f81c 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -493,24 +494,36 @@ bool ASTJsonConverter::visit(ModifierInvocation const& _node) bool ASTJsonConverter::visit(EventDefinition const& _node) { m_inEvent = true; - setJsonNode(_node, "EventDefinition", { + std::vector> _attributes = { make_pair("name", _node.name()), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("parameters", toJson(_node.parameterList())), make_pair("anonymous", _node.isAnonymous()) - }); + }; + if (m_stackState >= CompilerStack::State::AnalysisPerformed) + _attributes.emplace_back( + make_pair( + "eventSelector", + toHex(u256(h256::Arith(util::keccak256(_node.functionType(true)->externalSignature())))) + )); + + setJsonNode(_node, "EventDefinition", std::move(_attributes)); return false; } bool ASTJsonConverter::visit(ErrorDefinition const& _node) { - setJsonNode(_node, "ErrorDefinition", { + std::vector> _attributes = { make_pair("name", _node.name()), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("parameters", toJson(_node.parameterList())) - }); + }; + if (m_stackState >= CompilerStack::State::AnalysisPerformed) + _attributes.emplace_back(make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex())); + + setJsonNode(_node, "ErrorDefinition", std::move(_attributes)); return false; } diff --git a/test/libsolidity/ASTJSON/documentation.json b/test/libsolidity/ASTJSON/documentation.json index de512181f..f31382d3a 100644 --- a/test/libsolidity/ASTJSON/documentation.json +++ b/test/libsolidity/ASTJSON/documentation.json @@ -162,6 +162,7 @@ "src": "69:26:3", "text": "Some comment on Evt." }, + "eventSelector": "a69007916fc1145953e5a7032d7c3eab4b8e2f33ec59b0f71e732904eeede3a4", "id": 12, "name": "Evt", "nameLocation": "102:3:3", diff --git a/test/libsolidity/ASTJSON/event_definition.json b/test/libsolidity/ASTJSON/event_definition.json index 627fd13ba..0bb614c22 100644 --- a/test/libsolidity/ASTJSON/event_definition.json +++ b/test/libsolidity/ASTJSON/event_definition.json @@ -30,6 +30,7 @@ [ { "anonymous": false, + "eventSelector": "92bbf6e823a631f3c8e09b1c8df90f378fb56f7fbc9701827e1ff8aad7f6a028", "id": 2, "name": "E", "nameLocation": "19:1:1", diff --git a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.json b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol new file mode 100644 index 000000000..a22910570 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol @@ -0,0 +1,5 @@ +contract C { + event E(function() internal); +} + +// ---- diff --git a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json new file mode 100644 index 000000000..0c90ee840 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json @@ -0,0 +1,78 @@ +{ + "absolutePath": "a", + "id": 8, + "nodeType": "SourceUnit", + "nodes": + [ + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "contract", + "id": 7, + "name": "C", + "nameLocation": "9:1:1", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "anonymous": false, + "id": 6, + "name": "E", + "nameLocation": "23:1:1", + "nodeType": "EventDefinition", + "parameters": + { + "id": 5, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 4, + "indexed": false, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "src": "25:20:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": {}, + "typeName": + { + "id": 3, + "nodeType": "FunctionTypeName", + "parameterTypes": + { + "id": 1, + "nodeType": "ParameterList", + "parameters": [], + "src": "33:2:1" + }, + "returnParameterTypes": + { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "44:0:1" + }, + "src": "25:20:1", + "stateMutability": "nonpayable", + "typeDescriptions": {}, + "visibility": "internal" + }, + "visibility": "internal" + } + ], + "src": "24:21:1" + }, + "src": "17:29:1" + } + ], + "src": "0:48:1", + "usedErrors": [] + } + ], + "src": "0:49:1" +} diff --git a/test/libsolidity/ASTJSON/used_errors.json b/test/libsolidity/ASTJSON/used_errors.json index a8ca24a28..a0e8e28ba 100644 --- a/test/libsolidity/ASTJSON/used_errors.json +++ b/test/libsolidity/ASTJSON/used_errors.json @@ -20,6 +20,7 @@ "nodes": [ { + "errorSelector": "c1599bd9", "id": 2, "name": "X", "nameLocation": "6:1:1", @@ -127,6 +128,7 @@ "nodes": [ { + "errorSelector": "2bc80f3a", "id": 11, "name": "T", "nameLocation": "63:1:1", @@ -145,7 +147,7 @@ { "id": 17, "nodeType": "Block", - "src": "97:8:1", + "src": "92:8:1", "statements": [ { @@ -160,7 +162,7 @@ "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 9, - "src": "99:1:1", + "src": "94:1:1", "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", @@ -175,7 +177,7 @@ "lValueRequested": false, "names": [], "nodeType": "FunctionCall", - "src": "99:3:1", + "src": "94:3:1", "tryCall": false, "typeDescriptions": { @@ -185,7 +187,7 @@ }, "id": 16, "nodeType": "ExpressionStatement", - "src": "99:3:1" + "src": "94:3:1" } ] }, @@ -209,17 +211,17 @@ "id": 13, "nodeType": "ParameterList", "parameters": [], - "src": "97:0:1" + "src": "92:0:1" }, "scope": 19, - "src": "72:33:1", - "stateMutability": "pure", + "src": "72:28:1", + "stateMutability": "nonpayable", "virtual": false, "visibility": "public" } ], "scope": 20, - "src": "40:67:1", + "src": "40:62:1", "usedErrors": [ 2, @@ -227,5 +229,5 @@ ] } ], - "src": "0:108:1" + "src": "0:103:1" } diff --git a/test/libsolidity/ASTJSON/used_errors.sol b/test/libsolidity/ASTJSON/used_errors.sol index e891a20ee..ead3e2dcf 100644 --- a/test/libsolidity/ASTJSON/used_errors.sol +++ b/test/libsolidity/ASTJSON/used_errors.sol @@ -2,7 +2,7 @@ error X(); function f() { revert X(); } contract C { error T(); - function h() public pure { f(); } + function h() public { f(); } } // ---- diff --git a/test/libsolidity/ASTJSON/used_errors_parseOnly.json b/test/libsolidity/ASTJSON/used_errors_parseOnly.json index 162f441c4..58b476005 100644 --- a/test/libsolidity/ASTJSON/used_errors_parseOnly.json +++ b/test/libsolidity/ASTJSON/used_errors_parseOnly.json @@ -108,7 +108,7 @@ { "id": 17, "nodeType": "Block", - "src": "97:8:1", + "src": "92:8:1", "statements": [ { @@ -121,19 +121,19 @@ "name": "f", "nodeType": "Identifier", "overloadedDeclarations": [], - "src": "99:1:1", + "src": "94:1:1", "typeDescriptions": {} }, "id": 15, "names": [], "nodeType": "FunctionCall", - "src": "99:3:1", + "src": "94:3:1", "tryCall": false, "typeDescriptions": {} }, "id": 16, "nodeType": "ExpressionStatement", - "src": "99:3:1" + "src": "94:3:1" } ] }, @@ -156,17 +156,17 @@ "id": 13, "nodeType": "ParameterList", "parameters": [], - "src": "97:0:1" + "src": "92:0:1" }, - "src": "72:33:1", - "stateMutability": "pure", + "src": "72:28:1", + "stateMutability": "nonpayable", "virtual": false, "visibility": "public" } ], - "src": "40:67:1", + "src": "40:62:1", "usedErrors": [] } ], - "src": "0:108:1" + "src": "0:103:1" } From 49f06dacdf82589712d8080c9df4f46d8bf8b2e1 Mon Sep 17 00:00:00 2001 From: Richie Date: Tue, 15 Feb 2022 19:24:44 -0800 Subject: [PATCH 16/45] fix: remove lower_case_with_underscores and Capitalized_Words_With_Underscores from code examples --- docs/050-breaking-changes.rst | 12 ++++---- docs/assembly.rst | 12 ++++---- docs/contracts/functions.rst | 8 +++--- docs/style-guide.rst | 16 +++++------ docs/types/mapping-types.rst | 18 ++++++------ docs/types/reference-types.rst | 52 +++++++++++++++++----------------- 6 files changed, 58 insertions(+), 60 deletions(-) diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst index 90af86526..3f41ac860 100644 --- a/docs/050-breaking-changes.rst +++ b/docs/050-breaking-changes.rst @@ -89,8 +89,8 @@ For most of the topics the compiler will provide suggestions. * Explicit data location for all variables of struct, array or mapping types is now mandatory. This is also applied to function parameters and return - variables. For example, change ``uint[] x = m_x`` to ``uint[] storage x = - m_x``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)`` + variables. For example, change ``uint[] x = z`` to ``uint[] storage x = + z``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)`` where ``memory`` is the data location and might be replaced by ``storage`` or ``calldata`` accordingly. Note that ``external`` functions require parameters with a data location of ``calldata``. @@ -483,7 +483,7 @@ New version: return data; } - using address_make_payable for address; + using AddressMakePayable for address; // Data location for 'arr' must be specified function g(uint[] memory /* arr */, bytes8 x, OtherContract otherContract, address unknownContract) public payable { // 'otherContract.transfer' is not provided. @@ -500,7 +500,7 @@ New version: // 'address payable' should be used whenever possible. // To increase clarity, we suggest the use of a library for // the conversion (provided after the contract in this example). - address payable addr = unknownContract.make_payable(); + address payable addr = unknownContract.makePayable(); require(addr.send(1 ether)); // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), @@ -516,8 +516,8 @@ New version: // We can define a library for explicitly converting ``address`` // to ``address payable`` as a workaround. - library address_make_payable { - function make_payable(address x) internal pure returns (address payable) { + library AddressMakePayable { + function makePayable(address x) internal pure returns (address payable) { return address(uint160(x)); } } diff --git a/docs/assembly.rst b/docs/assembly.rst index c26a53e49..5427e0f51 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -45,19 +45,19 @@ Solidity language without a compiler change. pragma solidity >=0.4.16 <0.9.0; library GetCode { - function at(address _addr) public view returns (bytes memory o_code) { + function at(address _addr) public view returns (bytes memory code) { assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(_addr) // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) + // by using code = new bytes(size) + code := mload(0x40) // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // store length in memory - mstore(o_code, size) + mstore(code, size) // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) + extcodecopy(_addr, add(code, 0x20), 0, size) } } } diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index ff49e4f28..cada0e5d9 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -102,10 +102,10 @@ two integers passed as function parameters, then you use something like: function arithmetic(uint _a, uint _b) public pure - returns (uint o_sum, uint o_product) + returns (uint sum, uint product) { - o_sum = _a + _b; - o_product = _a * _b; + sum = _a + _b; + product = _a * _b; } } @@ -129,7 +129,7 @@ statement: function arithmetic(uint _a, uint _b) public pure - returns (uint o_sum, uint o_product) + returns (uint sum, uint product) { return (_a + _b, _a * _b); } diff --git a/docs/style-guide.rst b/docs/style-guide.rst index a3d3f69a5..3b76273cc 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -204,7 +204,7 @@ Yes: .. code-block:: solidity - thisIsALongNestedMapping[being][set][to_some_value] = someFunction( + thisIsALongNestedMapping[being][set][toSomeValue] = someFunction( argument1, argument2, argument3, @@ -215,7 +215,7 @@ No: .. code-block:: solidity - thisIsALongNestedMapping[being][set][to_some_value] = someFunction(argument1, + thisIsALongNestedMapping[being][set][toSomeValue] = someFunction(argument1, argument2, argument3, argument4); @@ -439,15 +439,15 @@ Yes: x = 1; y = 2; - long_variable = 3; + longVariable = 3; No: .. code-block:: solidity - x = 1; - y = 2; - long_variable = 3; + x = 1; + y = 2; + longVariable = 3; Don't include a whitespace in the receive and fallback functions: @@ -1092,12 +1092,10 @@ naming styles. * ``b`` (single lowercase letter) * ``B`` (single uppercase letter) * ``lowercase`` -* ``lower_case_with_underscores`` * ``UPPERCASE`` * ``UPPER_CASE_WITH_UNDERSCORES`` * ``CapitalizedWords`` (or CapWords) * ``mixedCase`` (differs from CapitalizedWords by initial lowercase character!) -* ``Capitalized_Words_With_Underscores`` .. note:: When using initialisms in CapWords, capitalize all the letters of the initialisms. Thus HTTPServerError is better than HttpServerError. When using initialisms in mixedCase, capitalize all the letters of the initialisms, except keep the first one lower case if it is the beginning of the name. Thus xmlHTTPRequest is better than XMLHTTPRequest. @@ -1256,7 +1254,7 @@ Enums, in the style of simple type declarations, should be named using the CapWo Avoiding Naming Collisions ========================== -* ``single_trailing_underscore_`` +* ``singleTrailingUnderscore_`` This convention is suggested when the desired name collides with that of a built-in or otherwise reserved name. diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst index 18f3bf827..2b6d284bf 100644 --- a/docs/types/mapping-types.rst +++ b/docs/types/mapping-types.rst @@ -166,22 +166,22 @@ the ``sum`` function iterates over to sum all the values. return self.data[key].keyIndex > 0; } - function iterate_start(itmap storage self) internal view returns (uint keyIndex) { - return iterate_next(self, type(uint).max); + function iterateStart(itmap storage self) internal view returns (uint keyIndex) { + return iterateNext(self, type(uint).max); } - function iterate_valid(itmap storage self, uint keyIndex) internal view returns (bool) { + function iterateValid(itmap storage self, uint keyIndex) internal view returns (bool) { return keyIndex < self.keys.length; } - function iterate_next(itmap storage self, uint keyIndex) internal view returns (uint r_keyIndex) { + function iterateNext(itmap storage self, uint keyIndex) internal view returns (uint r_keyIndex) { keyIndex++; while (keyIndex < self.keys.length && self.keys[keyIndex].deleted) keyIndex++; return keyIndex; } - function iterate_get(itmap storage self, uint keyIndex) internal view returns (uint key, uint value) { + function iterateGet(itmap storage self, uint keyIndex) internal view returns (uint key, uint value) { key = self.keys[keyIndex].key; value = self.data[key].value; } @@ -206,11 +206,11 @@ the ``sum`` function iterates over to sum all the values. // Computes the sum of all stored data. function sum() public view returns (uint s) { for ( - uint i = data.iterate_start(); - data.iterate_valid(i); - i = data.iterate_next(i) + uint i = data.iterateStart(); + data.iterateValid(i); + i = data.iterateNext(i) ) { - (, uint value) = data.iterate_get(i); + (, uint value) = data.iterateGet(i); s += value; } } diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 014c49935..f595612c0 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -190,11 +190,11 @@ If you want to use string parameters or other types that are not implicitly conv contract C { string s = "Storage"; function f(bytes calldata bc, string memory sm, bytes16 b) public view { - string memory concat_string = string.concat(s, string(bc), "Literal", sm); - assert((bytes(s).length + bc.length + 7 + bytes(sm).length) == bytes(concat_string).length); + string memory concatString = string.concat(s, string(bc), "Literal", sm); + assert((bytes(s).length + bc.length + 7 + bytes(sm).length) == bytes(concatString).length); - bytes memory concat_bytes = bytes.concat(bytes(s), bc, bc[:2], "Literal", bytes(sm), b); - assert((bytes(s).length + bc.length + 2 + 7 + bytes(sm).length + b.length) == concat_bytes.length); + bytes memory concatBytes = bytes.concat(bytes(s), bc, bc[:2], "Literal", bytes(sm), b); + assert((bytes(s).length + bc.length + 2 + 7 + bytes(sm).length + b.length) == concatBytes.length); } } @@ -376,20 +376,20 @@ Array Members pragma solidity >=0.6.0 <0.9.0; contract ArrayContract { - uint[2**20] m_aLotOfIntegers; + uint[2**20] aLotOfIntegers; // Note that the following is not a pair of dynamic arrays but a // dynamic array of pairs (i.e. of fixed size arrays of length two). // Because of that, T[] is always a dynamic array of T, even if T // itself is an array. // Data location for all state variables is storage. - bool[2][] m_pairsOfFlags; + bool[2][] pairsOfFlags; // newPairs is stored in memory - the only possibility // for public contract function arguments function setAllFlagPairs(bool[2][] memory newPairs) public { // assignment to a storage array performs a copy of ``newPairs`` and - // replaces the complete array ``m_pairsOfFlags``. - m_pairsOfFlags = newPairs; + // replaces the complete array ``pairsOfFlags``. + pairsOfFlags = newPairs; } struct StructType { @@ -411,45 +411,45 @@ Array Members function setFlagPair(uint index, bool flagA, bool flagB) public { // access to a non-existing index will throw an exception - m_pairsOfFlags[index][0] = flagA; - m_pairsOfFlags[index][1] = flagB; + pairsOfFlags[index][0] = flagA; + pairsOfFlags[index][1] = flagB; } function changeFlagArraySize(uint newSize) public { // using push and pop is the only way to change the // length of an array - if (newSize < m_pairsOfFlags.length) { - while (m_pairsOfFlags.length > newSize) - m_pairsOfFlags.pop(); - } else if (newSize > m_pairsOfFlags.length) { - while (m_pairsOfFlags.length < newSize) - m_pairsOfFlags.push(); + if (newSize < pairsOfFlags.length) { + while (pairsOfFlags.length > newSize) + pairsOfFlags.pop(); + } else if (newSize > pairsOfFlags.length) { + while (pairsOfFlags.length < newSize) + pairsOfFlags.push(); } } function clear() public { // these clear the arrays completely - delete m_pairsOfFlags; - delete m_aLotOfIntegers; + delete pairsOfFlags; + delete aLotOfIntegers; // identical effect here - m_pairsOfFlags = new bool[2][](0); + pairsOfFlags = new bool[2][](0); } - bytes m_byteData; + bytes byteData; function byteArrays(bytes memory data) public { // byte arrays ("bytes") are different as they are stored without padding, // but can be treated identical to "uint8[]" - m_byteData = data; + byteData = data; for (uint i = 0; i < 7; i++) - m_byteData.push(); - m_byteData[3] = 0x08; - delete m_byteData[2]; + byteData.push(); + byteData[3] = 0x08; + delete byteData[2]; } function addFlag(bool[2] memory flag) public returns (uint) { - m_pairsOfFlags.push(flag); - return m_pairsOfFlags.length; + pairsOfFlags.push(flag); + return pairsOfFlags.length; } function createMemoryArray(uint size) public pure returns (bytes memory) { From c5070d8633bb03eb0e59027cbc8891421c4c7b92 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 22 Feb 2022 10:22:11 +0100 Subject: [PATCH 17/45] Update .github/CODEOWNERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Åšliwak --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1f6c29d6c..d50c44566 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -docs/style-guide.rst @fulldecent +/docs/style-guide.rst @fulldecent From 50ae21d1bfaf016a6e8f467dcde6bca65a753af7 Mon Sep 17 00:00:00 2001 From: a3d4 Date: Sun, 20 Feb 2022 02:36:11 +0100 Subject: [PATCH 18/45] Fix running tests from any drive --- libsolidity/interface/FileReader.cpp | 31 +++++++++++++++++------ libsolidity/interface/FileReader.h | 11 ++++++++ test/libsolidity/interface/FileReader.cpp | 5 ++-- test/solc/CommandLineInterface.cpp | 8 +++--- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index e581c4a56..8300feb57 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -276,14 +276,8 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( // If the path is on the same drive as the working dir, for portability we prefer not to // include the root name. Do this only for non-UNC paths - my experiments show that on Windows // when the working dir is an UNC path, / does not not actually refer to the root of the UNC path. - boost::filesystem::path normalizedRootPath = normalizedPath.root_path(); - if (!isUNCPath(normalizedPath)) - { - boost::filesystem::path workingDirRootPath = canonicalWorkDir.root_path(); - // Ignore drive letter case on Windows (C:\ <=> c:\). - if (boost::filesystem::equivalent(normalizedRootPath, workingDirRootPath)) - normalizedRootPath = "/"; - } + + boost::filesystem::path normalizedRootPath = normalizeCLIRootPathForVFS(normalizedPath, canonicalWorkDir); // lexically_normal() will not squash paths like "/../../" into "/". We have to do it manually. boost::filesystem::path dotDotPrefix = absoluteDotDotPrefix(normalizedPath); @@ -308,6 +302,27 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( return normalizedPathNoDotDot; } +boost::filesystem::path FileReader::normalizeCLIRootPathForVFS( + boost::filesystem::path const& _path, + boost::filesystem::path const& _workDir +) +{ + solAssert(_workDir.is_absolute(), ""); + + boost::filesystem::path absolutePath = boost::filesystem::absolute(_path, _workDir); + boost::filesystem::path rootPath = absolutePath.root_path(); + boost::filesystem::path baseRootPath = _workDir.root_path(); + + if (isUNCPath(absolutePath)) + return rootPath; + + // Ignore drive letter case on Windows (C:\ <=> c:\). + if (boost::filesystem::equivalent(rootPath, baseRootPath)) + return "/"; + + return rootPath; +} + bool FileReader::isPathPrefix(boost::filesystem::path const& _prefix, boost::filesystem::path const& _path) { solAssert(!_prefix.empty() && !_path.empty(), ""); diff --git a/libsolidity/interface/FileReader.h b/libsolidity/interface/FileReader.h index 3892e9826..f05ce894d 100644 --- a/libsolidity/interface/FileReader.h +++ b/libsolidity/interface/FileReader.h @@ -115,6 +115,17 @@ public: SymlinkResolution _symlinkResolution = SymlinkResolution::Disabled ); + /// Normalizes a root path by excluding, in some cases, its root name. + /// The function is used for better portability, and intended to omit root name + /// if the path can be used without it. + /// @param _path Path to normalize the root path. + /// @param _workDir Current working directory path, must be absolute. + /// @returns a normalized root path. + static boost::filesystem::path normalizeCLIRootPathForVFS( + boost::filesystem::path const& _path, + boost::filesystem::path const& _workDir = boost::filesystem::current_path() + ); + /// @returns true if all the path components of @a _prefix are present at the beginning of @a _path. /// Both paths must be absolute (or have slash as root) and normalized (no . or .. segments, no /// multiple consecutive slashes). diff --git a/test/libsolidity/interface/FileReader.cpp b/test/libsolidity/interface/FileReader.cpp index 39355e536..ea85685fd 100644 --- a/test/libsolidity/interface/FileReader.cpp +++ b/test/libsolidity/interface/FileReader.cpp @@ -313,8 +313,9 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_not_resolve_symlinks_unless_r if (!createSymlinkIfSupportedByFilesystem(tempDir.path() / "abc", tempDir.path() / "sym", true)) return; - boost::filesystem::path expectedPrefixWithSymlinks = "/" / tempDir.path().relative_path(); - boost::filesystem::path expectedPrefixWithoutSymlinks = "/" / boost::filesystem::weakly_canonical(tempDir).relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir); + boost::filesystem::path expectedPrefixWithSymlinks = expectedRootPath / tempDir.path().relative_path(); + boost::filesystem::path expectedPrefixWithoutSymlinks = expectedRootPath / boost::filesystem::weakly_canonical(tempDir).relative_path(); BOOST_CHECK_EQUAL( FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Disabled), diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 73c999f3f..169437f3c 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -178,8 +178,9 @@ BOOST_AUTO_TEST_CASE(cli_input) createFilesWithParentDirs({tempDir1.path() / "input1.sol"}); createFilesWithParentDirs({tempDir2.path() / "input2.sol"}); - boost::filesystem::path expectedDir1 = "/" / tempDir1.path().relative_path(); - boost::filesystem::path expectedDir2 = "/" / tempDir2.path().relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir1); + boost::filesystem::path expectedDir1 = expectedRootPath / tempDir1.path().relative_path(); + boost::filesystem::path expectedDir2 = expectedRootPath / tempDir2.path().relative_path(); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); soltestAssert(expectedDir2.is_absolute() || expectedDir2.root_path() == "/", ""); @@ -223,7 +224,8 @@ BOOST_AUTO_TEST_CASE(cli_ignore_missing_some_files_exist) TemporaryDirectory tempDir2(TEST_CASE_NAME); createFilesWithParentDirs({tempDir1.path() / "input1.sol"}); - boost::filesystem::path expectedDir1 = "/" / tempDir1.path().relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir1); + boost::filesystem::path expectedDir1 = expectedRootPath / tempDir1.path().relative_path(); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); // NOTE: Allowed paths should not be added for skipped files. From b741ca3ab5148c5be9ea47a38c083b1b94688c92 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 21 Feb 2022 20:55:41 -0500 Subject: [PATCH 19/45] scripts/common.sh: 'diff --color' not supported by macOS. --- scripts/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/common.sh b/scripts/common.sh index 4a98c0072..7cb96ed02 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -180,7 +180,7 @@ function diff_values shift shift - diff --color=auto --unified=0 <(echo "$value1") <(echo "$value2") "$@" + diff --unified=0 <(echo "$value1") <(echo "$value2") "$@" } function safe_kill From 1f9fab84a648068080ee79e1263351b4f9632324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 24 Feb 2022 17:54:17 +0100 Subject: [PATCH 20/45] Remove release.sh/.bat scripts we no longer use --- .../fix_homebrew_paths_in_standalone_zip.py | 66 ------------------- scripts/release.bat | 38 ----------- scripts/release.sh | 56 ---------------- 3 files changed, 160 deletions(-) delete mode 100755 scripts/fix_homebrew_paths_in_standalone_zip.py delete mode 100644 scripts/release.bat delete mode 100755 scripts/release.sh diff --git a/scripts/fix_homebrew_paths_in_standalone_zip.py b/scripts/fix_homebrew_paths_in_standalone_zip.py deleted file mode 100755 index 43f26795c..000000000 --- a/scripts/fix_homebrew_paths_in_standalone_zip.py +++ /dev/null @@ -1,66 +0,0 @@ -# ------------------------------------------------------------------------------ -# This Python script is used within the OS X release process, to ensure -# that the standalone OS X ZIP files which we make are actually -# standalone, and not implicitly dependent on Homebrew installs for -# external libraries which we use. -# -# This implicit dependencies seem to show up only where we have -# external dependencies which are dependent on each other, and the -# path from one to another is an absolute path to "/usr/local/opt", -# the Homebrew install location. External dependencies which only -# depend on system libraries are fine. Our main applications seem -# to be fine. -# -# An example of a dependency which requires this fix-up at the time -# of writing is the following dependency edge: -# -# libjsonrpccpp-client.0.dylib -# -> /usr/local/opt/jsoncpp/lib/libjsoncpp.0.dylib -# -# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac -# for a little overview of "install_name_tool" and "otool". -# -# ------------------------------------------------------------------------------ -# 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 -# -# (c) 2016 solidity contributors. -# ----------------------------------------------------------------------------- - -import os -import subprocess -import sys - -def readDependencies(fname): - with subprocess.Popen(['otool', '-L', fname], stdout=subprocess.PIPE) as o: - for line in o.stdout: - if line[0] == '\t': - library = line.split(' ', 1)[0][1:] - if (library.startswith("/usr/local/lib") or - library.startswith("/usr/local/opt") or - library.startswith("/Users/") - ): - if os.path.basename(library) != os.path.basename(fname): - command = "install_name_tool -change " + \ - library + " @executable_path/./" + \ - os.path.basename(library) + " " + fname - print(command) - os.system("chmod +w " + fname) - os.system(command) - -root = sys.argv[1] -for (dirpath, dirnames, filenames) in os.walk(root): - for filename in filenames: - readDependencies(os.path.join(root, filename)) diff --git a/scripts/release.bat b/scripts/release.bat deleted file mode 100644 index a1a909ae0..000000000 --- a/scripts/release.bat +++ /dev/null @@ -1,38 +0,0 @@ -@ECHO OFF - -REM --------------------------------------------------------------------------- -REM Batch file for implementing release flow for solidity for Windows. -REM -REM The documentation for solidity is hosted at: -REM -REM https://docs.soliditylang.org -REM -REM --------------------------------------------------------------------------- -REM This file is part of solidity. -REM -REM solidity is free software: you can redistribute it and/or modify -REM it under the terms of the GNU General Public License as published by -REM the Free Software Foundation, either version 3 of the License, or -REM (at your option) any later version. -REM -REM solidity is distributed in the hope that it will be useful, -REM but WITHOUT ANY WARRANTY; without even the implied warranty of -REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -REM GNU General Public License for more details. -REM -REM You should have received a copy of the GNU General Public License -REM along with solidity. If not, see -REM -REM Copyright (c) 2016 solidity contributors. -REM --------------------------------------------------------------------------- - -set CONFIGURATION=%1 -set VERSION=%2 - -set "DLLS=MSVC_DLLS_NOT_FOUND" -FOR /d %%d IN ("C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\*" - "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\*") DO set "DLLS=%%d\x86\Microsoft.VC141.CRT\msvc*.dll" - -7z a solidity-windows.zip ^ - .\build\solc\%CONFIGURATION%\solc.exe .\build\test\%CONFIGURATION%\soltest.exe ^ - "%DLLS%" diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 88aaa5fef..000000000 --- a/scripts/release.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -#------------------------------------------------------------------------------ -# Bash script implementing release flow for solidity for Linux and macOS. -# -# TODO - At the time of writing, we only have ZIPs working. Need to hook up -# support for Homebrew and PPAs. -# -# The documentation for solidity is hosted at: -# -# https://docs.soliditylang.org -# -# ------------------------------------------------------------------------------ -# 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 -# -# (c) 2016 solidity contributors. -#------------------------------------------------------------------------------ - -ZIP_SUFFIX="$1" -ZIP_TEMP_DIR="$(pwd)/build/zip/" - -# There is an implicit assumption here that we HAVE to run from root directory. -REPO_ROOT=$(pwd) - -mkdir -p "$ZIP_TEMP_DIR" - -# Copy all the solidity executables into a temporary directory prior to ZIP creation - -cp "$REPO_ROOT/build/solc/solc" "$ZIP_TEMP_DIR" - -# For macOS, we run a fix-up script which alters all of the symbolic links within -# the executables and dynamic libraries such that the ZIP becomes self-contained, by -# revectoring all the dylib references to be relative to the directory containing the -# application, so that the ZIPs are self-contained, with the only external references -# being for kernel-level dylibs. - -if [[ "$OSTYPE" == "darwin"* ]]; then - python3 "$REPO_ROOT/scripts/fix_homebrew_paths_in_standalone_zip.py" "$ZIP_TEMP_DIR" -fi - -# And ZIP it all up, with a filename suffix passed in on the command-line. -mkdir -p "$REPO_ROOT/upload" -zip -j "$REPO_ROOT/upload/solidity-$ZIP_SUFFIX.zip" "$ZIP_TEMP_DIR/"* From 1762482a565e394d5efc6f8a4fd401359dbfcfe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 24 Feb 2022 17:57:10 +0100 Subject: [PATCH 21/45] Add instructions for creating the source tarball back to the release checklist --- ReleaseChecklist.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 39a3d9a32..6d5008cb3 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -26,7 +26,11 @@ - [ ] Click the `PUBLISH RELEASE` button on the release page, creating the tag. - [ ] Wait for the CI runs on the tag itself. -### Download Binaries +### Upload Release Artifacts + - [ ] Switch to the tag that archives have to be created for. + - [ ] Create the ``prerelease.txt`` file: (``echo -n > prerelease.txt``). + - [ ] Run ``scripts/create_source_tarball.sh`` while being on the tag to create the source tarball. This will create the tarball in a directory called ``upload``. + - [ ] Take the tarball from the upload directory (its name should be ``solidity_x.x.x.tar.gz``, otherwise ``prerelease.txt`` was missing in the step before) and upload the source tarball to the release page. - [ ] Take the ``solc.exe`` binary from the ``b_win_release`` run of the released commit in circle-ci and add it to the release page as ``solc-windows.exe``. - [ ] Take the ``solc`` binary from the ``b_osx`` run of the released commit in circle-ci and add it to the release page as ``solc-macos``. - [ ] Take the ``solc`` binary from the ``b_ubu_static`` run of the released commit in circle-ci and add it to the release page as ``solc-static-linux``. From fb7cdda89162bfc9c3f173e03016783896e0627e Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 28 Feb 2022 17:57:19 +0100 Subject: [PATCH 22/45] Fix iterable mapping example. --- docs/types/mapping-types.rst | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst index 2b6d284bf..399523cf2 100644 --- a/docs/types/mapping-types.rst +++ b/docs/types/mapping-types.rst @@ -126,7 +126,7 @@ the ``sum`` function iterates over to sum all the values. :force: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.6.8 <0.9.0; + pragma solidity ^0.8.8; struct IndexValue { uint keyIndex; uint value; } struct KeyFlag { uint key; bool deleted; } @@ -137,6 +137,8 @@ the ``sum`` function iterates over to sum all the values. uint size; } + type Iterator is uint; + library IterableMapping { function insert(itmap storage self, uint key, uint value) internal returns (bool replaced) { uint keyIndex = self.data[key].keyIndex; @@ -166,25 +168,29 @@ the ``sum`` function iterates over to sum all the values. return self.data[key].keyIndex > 0; } - function iterateStart(itmap storage self) internal view returns (uint keyIndex) { - return iterateNext(self, type(uint).max); + function iterateStart(itmap storage self) internal view returns (Iterator) { + return iteratorSkipDeleted(self, 0); } - function iterateValid(itmap storage self, uint keyIndex) internal view returns (bool) { - return keyIndex < self.keys.length; + function iterateValid(itmap storage self, Iterator iterator) internal view returns (bool) { + return Iterator.unwrap(iterator) < self.keys.length; } - function iterateNext(itmap storage self, uint keyIndex) internal view returns (uint r_keyIndex) { - keyIndex++; - while (keyIndex < self.keys.length && self.keys[keyIndex].deleted) - keyIndex++; - return keyIndex; + function iterateNext(itmap storage self, Iterator iterator) internal view returns (Iterator) { + return iteratorSkipDeleted(self, Iterator.unwrap(iterator) + 1); } - function iterateGet(itmap storage self, uint keyIndex) internal view returns (uint key, uint value) { + function iterateGet(itmap storage self, Iterator iterator) internal view returns (uint key, uint value) { + uint keyIndex = Iterator.unwrap(iterator); key = self.keys[keyIndex].key; value = self.data[key].value; } + + function iteratorSkipDeleted(itmap storage self, uint keyIndex) private view returns (Iterator) { + while (keyIndex < self.keys.length && self.keys[keyIndex].deleted) + keyIndex++; + return Iterator.wrap(keyIndex); + } } // How to use it @@ -206,7 +212,7 @@ the ``sum`` function iterates over to sum all the values. // Computes the sum of all stored data. function sum() public view returns (uint s) { for ( - uint i = data.iterateStart(); + Iterator i = data.iterateStart(); data.iterateValid(i); i = data.iterateNext(i) ) { From bef69b595b17ac3cd9c7b060aad400d6b6f99da2 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Mon, 28 Feb 2022 18:56:20 +0100 Subject: [PATCH 23/45] Ignore cex in SMT test --- .../smtCheckerTests/userTypes/multisource_module.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol b/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol index 491b8600d..846f3ab75 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol @@ -16,6 +16,7 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6328: (s2.sol:259-292): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.h()\n C.f(5) -- internal call\n C.f(5) -- internal call -// Warning 6328: (s2.sol:346-377): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.h()\n C.f(5) -- internal call\n C.f(5) -- internal call\n C.g(1) -- internal call\n C.g(1) -- internal call +// Warning 6328: (s2.sol:259-292): CHC: Assertion violation happens here. +// Warning 6328: (s2.sol:346-377): CHC: Assertion violation happens here. From 5134dafb8e5184aeed73be30066f8e22591e0254 Mon Sep 17 00:00:00 2001 From: Callis Ezenwaka Date: Thu, 17 Feb 2022 00:28:34 +0100 Subject: [PATCH 24/45] Update typo in using-for.rst Update typo in using-for.rst --- docs/assembly.rst | 2 +- docs/contracts/using-for.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index 5427e0f51..e6dc6519c 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -139,7 +139,7 @@ the variable will not point beyond ``calldatasize()`` is performed. For external function pointers the address and the function selector can be accessed using ``x.address`` and ``x.selector``. The selector consists of four right-aligned bytes. -Both values are can be assigned to. For example: +Both values can be assigned to. For example: .. code-block:: solidity :force: diff --git a/docs/contracts/using-for.rst b/docs/contracts/using-for.rst index 582409904..af6750f87 100644 --- a/docs/contracts/using-for.rst +++ b/docs/contracts/using-for.rst @@ -120,7 +120,7 @@ It is also possible to extend elementary types in that way: } Note that all external library calls are actual EVM function calls. This means that -if you pass memory or value types, a copy will be performed, even of the +if you pass memory or value types, a copy will be performed, even in case of the ``self`` variable. The only situation where no copy will be performed is when storage reference variables are used or when internal library functions are called. From d0d4bca35b206cdaf2bcb34b51dda26081d57e06 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 15 Feb 2022 16:19:55 +0100 Subject: [PATCH 25/45] Extend side effects to operations. --- libevmasm/SemanticInformation.cpp | 131 ++++++++++++++++++++++++++++-- libevmasm/SemanticInformation.h | 26 ++++++ 2 files changed, 151 insertions(+), 6 deletions(-) diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 41dc07fcf..8a1266bcf 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -29,6 +29,125 @@ using namespace std; using namespace solidity; using namespace solidity::evmasm; +vector SemanticInformation::readWriteOperations(Instruction _instruction) +{ + switch (_instruction) + { + case Instruction::SSTORE: + case Instruction::SLOAD: + { + assertThrow(memory(_instruction) == Effect::None, OptimizerException, ""); + assertThrow(storage(_instruction) != Effect::None, OptimizerException, ""); + Operation op; + op.effect = storage(_instruction); + op.location = Location::Storage; + op.startParameter = 0; + // We know that exactly one slot is affected. + op.lengthConstant = 1; + return {op}; + } + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::MLOAD: + { + assertThrow(memory(_instruction) != Effect::None, OptimizerException, ""); + assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); + Operation op; + op.effect = memory(_instruction); + op.location = Location::Memory; + op.startParameter = 0; + if (_instruction == Instruction::MSTORE || _instruction == Instruction::MLOAD) + op.lengthConstant = 32; + else if (_instruction == Instruction::MSTORE8) + op.lengthConstant = 1; + + return {op}; + } + case Instruction::REVERT: + case Instruction::RETURN: + case Instruction::KECCAK256: + case Instruction::LOG0: + case Instruction::LOG1: + case Instruction::LOG2: + case Instruction::LOG3: + case Instruction::LOG4: + { + assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); + assertThrow(memory(_instruction) == Effect::Read, OptimizerException, ""); + Operation op; + op.effect = memory(_instruction); + op.location = Location::Memory; + op.startParameter = 0; + op.lengthParameter = 1; + return {op}; + } + case Instruction::EXTCODECOPY: + { + assertThrow(memory(_instruction) == Effect::Write, OptimizerException, ""); + assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); + Operation op; + op.effect = memory(_instruction); + op.location = Location::Memory; + op.startParameter = 1; + op.lengthParameter = 3; + return {op}; + } + case Instruction::CODECOPY: + case Instruction::CALLDATACOPY: + case Instruction::RETURNDATACOPY: + { + assertThrow(memory(_instruction) == Effect::Write, OptimizerException, ""); + assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); + Operation op; + op.effect = memory(_instruction); + op.location = Location::Memory; + op.startParameter = 0; + op.lengthParameter = 2; + return {op}; + } + case Instruction::STATICCALL: + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::DELEGATECALL: + { + size_t paramCount = static_cast(instructionInfo(_instruction).args); + vector operations{ + Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}}, + Operation{Location::Storage, Effect::Read, {}, {}, {}} + }; + if (_instruction != Instruction::STATICCALL) + operations.emplace_back(Operation{Location::Storage, Effect::Write, {}, {}, {}}); + operations.emplace_back(Operation{ + Location::Memory, + Effect::Write, + paramCount - 2, + paramCount - 1, + {} + }); + return operations; + } + case Instruction::CREATE: + case Instruction::CREATE2: + return vector{ + Operation{ + Location::Memory, + Effect::Read, + 1, + 2, + {} + }, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::Storage, Effect::Write, {}, {}, {}} + }; + case Instruction::MSIZE: + // This is just to satisfy the assert below. + return vector{}; + default: + assertThrow(storage(_instruction) == None && memory(_instruction) == None, AssemblyException, ""); + } + return {}; +} + bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool _msizeImportant) { switch (_item.type()) @@ -49,7 +168,7 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool case PushLibraryAddress: case PushImmutable: return false; - case Operation: + case evmasm::Operation: { if (isSwapInstruction(_item) || isDupInstruction(_item)) return false; @@ -79,7 +198,7 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item) { - if (_item.type() != Operation) + if (_item.type() != evmasm::Operation) return false; switch (_item.instruction()) { @@ -97,14 +216,14 @@ bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item) bool SemanticInformation::isDupInstruction(AssemblyItem const& _item) { - if (_item.type() != Operation) + if (_item.type() != evmasm::Operation) return false; return evmasm::isDupInstruction(_item.instruction()); } bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) { - if (_item.type() != Operation) + if (_item.type() != evmasm::Operation) return false; return evmasm::isSwapInstruction(_item.instruction()); } @@ -116,7 +235,7 @@ bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) { - if (_item.type() != Operation) + if (_item.type() != evmasm::Operation) return false; switch (_item.instruction()) { @@ -166,7 +285,7 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) { assertThrow(_item.type() != VerbatimBytecode, AssemblyException, ""); - if (_item.type() != Operation) + if (_item.type() != evmasm::Operation) return true; switch (_item.instruction()) diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 8ba2743c4..68693f959 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -45,6 +45,32 @@ struct SemanticInformation Write }; + enum class Location { Storage, Memory }; + + /** + * Represents a read or write operation from or to one of the data locations. + */ + struct Operation + { + Location location; + Effect effect; + /// Start of affected area as an index into the parameters. + /// Unknown if not provided. + std::optional startParameter; + /// Length of the affected area as an index into the parameters (if this is an opcode). + /// Unknown if neither this nor lengthConstant is provided. + std::optional lengthParameter; + /// Length as a constant. + /// Unknown if neither this nor lengthArgument is provided. + std::optional lengthConstant; + }; + + /// @returns the sequence of read write operations performed by the instruction. + /// Order matters. + /// For external calls, there is just one unknown read and one unknown write operation, + /// event though there might be multiple. + static std::vector readWriteOperations(Instruction _instruction); + /// @returns true if the given items starts a new block for common subexpression analysis. /// @param _msizeImportant if false, consider an operation non-breaking if its only side-effect is that it modifies msize. static bool breaksCSEAnalysisBlock(AssemblyItem const& _item, bool _msizeImportant); From 63f0a22c5d1f2621793db40bf33ddeeb514f598c Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 2 Mar 2022 13:49:40 +0100 Subject: [PATCH 26/45] Also save and restore the nesting depth. --- libyul/optimiser/UnusedStoreBase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libyul/optimiser/UnusedStoreBase.cpp b/libyul/optimiser/UnusedStoreBase.cpp index 8e34d172f..de13a23cc 100644 --- a/libyul/optimiser/UnusedStoreBase.cpp +++ b/libyul/optimiser/UnusedStoreBase.cpp @@ -73,6 +73,7 @@ void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) { ScopedSaveAndRestore outerAssignments(m_stores, {}); ScopedSaveAndRestore forLoopInfo(m_forLoopInfo, {}); + ScopedSaveAndRestore forLoopNestingDepth(m_forLoopNestingDepth, 0); (*this)(_functionDefinition.body); From 149a730f4a7f668124eae39b91da91b630b0ca72 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 1 Mar 2022 13:47:39 -0500 Subject: [PATCH 27/45] Update buildpacks to include jq. --- .../docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz | 4 ++-- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 4 ++-- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index fb79ea946..bbc554e0f 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="15" +LABEL version="16" ARG DEBIAN_FRONTEND=noninteractive @@ -32,7 +32,7 @@ RUN apt-get update; \ software-properties-common \ ninja-build git wget \ libbz2-dev zlib1g-dev git curl uuid-dev \ - pkg-config openjdk-8-jdk liblzma-dev unzip mlton m4; \ + pkg-config openjdk-8-jdk liblzma-dev unzip mlton m4 jq; \ apt-get install -qy python3-pip; # Install cmake 3.21.2 (minimum requirement is cmake 3.10) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 3ecf9143a..6a047aa27 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="10" +LABEL version="11" ARG DEBIAN_FRONTEND=noninteractive @@ -37,7 +37,7 @@ RUN set -ex; \ cmake ninja-build \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ - libcvc4-dev libz3-static-dev z3-static \ + libcvc4-dev libz3-static-dev z3-static jq \ ; \ apt-get install -qy python3-pip python3-sphinx; \ pip3 install codecov; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang index d262fa5fa..853969ecd 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="10" +LABEL version="11" ARG DEBIAN_FRONTEND=noninteractive @@ -38,7 +38,7 @@ RUN set -ex; \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ clang \ - libz3-static-dev \ + libz3-static-dev jq \ ; \ rm -rf /var/lib/apt/lists/* From b0dcd7b9158ce2c0233640a47ab256dae39a1468 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 2 Mar 2022 13:47:04 +0100 Subject: [PATCH 28/45] Split out disassemble to remove numeric from instruction includes. --- libevmasm/AssemblyItem.h | 1 + libevmasm/CMakeLists.txt | 2 + libevmasm/ConstantOptimiser.h | 1 + libevmasm/Disassemble.cpp | 76 ++++++++++++++++++++++ libevmasm/Disassemble.h | 38 +++++++++++ libevmasm/Instruction.cpp | 53 +-------------- libevmasm/Instruction.h | 18 ++--- libevmasm/SemanticInformation.h | 3 + libsolidity/interface/StandardCompiler.cpp | 2 +- libyul/backends/evm/EVMMetrics.h | 1 + libyul/optimiser/SimplificationRules.h | 1 + solc/CommandLineInterface.cpp | 1 + test/Common.h | 3 +- test/libevmasm/Assembler.cpp | 1 + test/libsolidity/SolidityOptimizer.cpp | 1 + test/libyul/ObjectCompilerTest.cpp | 1 + 16 files changed, 136 insertions(+), 67 deletions(-) create mode 100644 libevmasm/Disassemble.cpp create mode 100644 libevmasm/Disassemble.h diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 1cbfe768d..796a792e8 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 4e392aadd..6563b2c0f 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -11,6 +11,8 @@ set(sources ConstantOptimiser.h ControlFlowGraph.cpp ControlFlowGraph.h + Disassemble.cpp + Disassemble.h Exceptions.h ExpressionClasses.cpp ExpressionClasses.h diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index d094bff73..ece28d249 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -26,6 +26,7 @@ #include +#include #include #include diff --git a/libevmasm/Disassemble.cpp b/libevmasm/Disassemble.cpp new file mode 100644 index 000000000..aa5b2820c --- /dev/null +++ b/libevmasm/Disassemble.cpp @@ -0,0 +1,76 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include +#include +#include + +using namespace std; +using namespace solidity; +using namespace solidity::util; +using namespace solidity::evmasm; + + +void solidity::evmasm::eachInstruction( + bytes const& _mem, + function const& _onInstruction +) +{ + for (auto it = _mem.begin(); it < _mem.end(); ++it) + { + Instruction const instr{*it}; + int additional = 0; + if (isValidInstruction(instr)) + additional = instructionInfo(instr).additional; + + u256 data{}; + + // fill the data with the additional data bytes from the instruction stream + while (additional > 0 && std::next(it) < _mem.end()) + { + data <<= 8; + data |= *++it; + --additional; + } + + // pad the remaining number of additional octets with zeros + data <<= 8 * additional; + + _onInstruction(instr, data); + } +} + +string solidity::evmasm::disassemble(bytes const& _mem, string const& _delimiter) +{ + stringstream ret; + eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) { + if (!isValidInstruction(_instr)) + ret << "0x" << std::uppercase << std::hex << static_cast(_instr) << _delimiter; + else + { + InstructionInfo info = instructionInfo(_instr); + ret << info.name; + if (info.additional) + ret << " 0x" << std::uppercase << std::hex << _data; + ret << _delimiter; + } + }); + return ret.str(); +} diff --git a/libevmasm/Disassemble.h b/libevmasm/Disassemble.h new file mode 100644 index 000000000..cf194e24b --- /dev/null +++ b/libevmasm/Disassemble.h @@ -0,0 +1,38 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include + +#include + +#include +#include + +namespace solidity::evmasm +{ + +/// Iterate through EVM code and call a function on each instruction. +void eachInstruction(bytes const& _mem, std::function const& _onInstruction); + +/// Convert from EVM code to simple EVM assembly language. +std::string disassemble(bytes const& _mem, std::string const& _delimiter = " "); + +} diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 7ce36c254..e2ce48b7f 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -22,10 +22,6 @@ #include -#include -#include -#include - using namespace std; using namespace solidity; using namespace solidity::util; @@ -325,53 +321,6 @@ static std::map const c_instructionInfo = { Instruction::SELFDESTRUCT, { "SELFDESTRUCT", 0, 1, 0, true, Tier::Special } } }; -void solidity::evmasm::eachInstruction( - bytes const& _mem, - function const& _onInstruction -) -{ - for (auto it = _mem.begin(); it < _mem.end(); ++it) - { - auto instr = Instruction(*it); - int additional = 0; - if (isValidInstruction(instr)) - additional = instructionInfo(instr).additional; - - u256 data; - - // fill the data with the additional data bytes from the instruction stream - while (additional > 0 && std::next(it) < _mem.end()) - { - data <<= 8; - data |= *++it; - --additional; - } - - // pad the remaining number of additional octets with zeros - data <<= 8 * additional; - - _onInstruction(instr, data); - } -} - -string solidity::evmasm::disassemble(bytes const& _mem, string const& _delimiter) -{ - stringstream ret; - eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) { - if (!isValidInstruction(_instr)) - ret << "0x" << std::uppercase << std::hex << static_cast(_instr) << _delimiter; - else - { - InstructionInfo info = instructionInfo(_instr); - ret << info.name; - if (info.additional) - ret << " 0x" << std::uppercase << std::hex << _data; - ret << _delimiter; - } - }); - return ret.str(); -} - InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst) { try @@ -380,7 +329,7 @@ InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst) } catch (...) { - return InstructionInfo({"", 0, 0, 0, false, Tier::Invalid}); + return InstructionInfo({"(_inst)) + ">", 0, 0, 0, false, Tier::Invalid}); } } diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index ad6bc9796..52bda8bf1 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -25,8 +25,6 @@ #include #include #include -#include -#include namespace solidity::evmasm { @@ -217,25 +215,25 @@ inline bool isLogInstruction(Instruction _inst) /// @returns the number of PUSH Instruction _inst inline unsigned getPushNumber(Instruction _inst) { - return (uint8_t)_inst - unsigned(Instruction::PUSH1) + 1; + return static_cast(_inst) - unsigned(Instruction::PUSH1) + 1; } /// @returns the number of DUP Instruction _inst inline unsigned getDupNumber(Instruction _inst) { - return (uint8_t)_inst - unsigned(Instruction::DUP1) + 1; + return static_cast(_inst) - unsigned(Instruction::DUP1) + 1; } /// @returns the number of SWAP Instruction _inst inline unsigned getSwapNumber(Instruction _inst) { - return (uint8_t)_inst - unsigned(Instruction::SWAP1) + 1; + return static_cast(_inst) - unsigned(Instruction::SWAP1) + 1; } /// @returns the number of LOG Instruction _inst inline unsigned getLogNumber(Instruction _inst) { - return (uint8_t)_inst - unsigned(Instruction::LOG0); + return static_cast(_inst) - unsigned(Instruction::LOG0); } /// @returns the PUSH<_number> instruction @@ -266,7 +264,7 @@ inline Instruction logInstruction(unsigned _number) return Instruction(unsigned(Instruction::LOG0) + _number); } -enum class Tier : unsigned +enum class Tier { Zero = 0, // 0, Zero Base, // 2, Quick @@ -301,10 +299,4 @@ bool isValidInstruction(Instruction _inst); /// Convert from string mnemonic to Instruction type. extern const std::map c_instructions; -/// Iterate through EVM code and call a function on each instruction. -void eachInstruction(bytes const& _mem, std::function const& _onInstruction); - -/// Convert from EVM code to simple EVM assembly language. -std::string disassemble(bytes const& _mem, std::string const& _delimiter = " "); - } diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 68693f959..36aabd55f 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -26,6 +26,9 @@ #include +#include +#include + namespace solidity::evmasm { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 75876d935..93ac20b03 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index 19702b8f3..b67cb77cd 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace solidity::yul diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index d4da4a2b0..77018bb38 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index bafd3a735..24e4ee7dd 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include diff --git a/test/Common.h b/test/Common.h index f3ea9e6f4..e7e211d9e 100644 --- a/test/Common.h +++ b/test/Common.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -47,7 +48,7 @@ static constexpr auto heraFilename = "libhera.so"; static constexpr auto heraDownloadLink = "https://github.com/ewasm/hera/releases/download/v0.5.0/hera-0.5.0-linux-x86_64.tar.gz"; #endif -struct ConfigException : public util::Exception {}; +struct ConfigException: public util::Exception {}; struct CommonOptions { diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index c7f28f654..78e598bca 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 9c9d9a7e6..eb4102b15 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -25,6 +25,7 @@ #include #include +#include #include diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 256bced21..f22870952 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include From e6848caac1246650ac5108f9abd08ac877b0f592 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 3 Feb 2022 11:49:16 +0100 Subject: [PATCH 29/45] Allow annotating inline assembly as memory-safe. --- Changelog.md | 1 + libsolidity/analysis/DocStringTagParser.cpp | 66 +++++++++++++++++++ libsolidity/analysis/DocStringTagParser.h | 1 + libsolidity/ast/ASTAnnotations.h | 2 + libsolidity/codegen/ir/IRGenerationContext.h | 8 +-- libsolidity/codegen/ir/IRGenerator.cpp | 8 +-- .../codegen/ir/IRGeneratorForStatements.cpp | 3 +- .../inlineAssembly/invalid_natspec.sol | 14 ++++ .../inlineAssembly/natspec_memory_safe.sol | 6 ++ 9 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/natspec_memory_safe.sol diff --git a/Changelog.md b/Changelog.md index fd7dda584..181c386aa 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.13 (unreleased) Language Features: + * General: Allow annotating inline assembly as memory-safe to allow optimizations and stack limit evasion that rely on respecting Solidity's memory model. Compiler Features: diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp index 137cdb409..5dc68d97f 100644 --- a/libsolidity/analysis/DocStringTagParser.cpp +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -30,6 +30,7 @@ #include #include +#include #include @@ -162,6 +163,71 @@ bool DocStringTagParser::visit(ErrorDefinition const& _error) return true; } +bool DocStringTagParser::visit(InlineAssembly const& _assembly) +{ + if (!_assembly.documentation()) + return true; + StructuredDocumentation documentation{-1, _assembly.location(), _assembly.documentation()}; + ErrorList errors; + ErrorReporter errorReporter{errors}; + auto docTags = DocStringParser{documentation, errorReporter}.parse(); + + if (!errors.empty()) + { + SecondarySourceLocation ssl; + for (auto const& error: errors) + if (error->comment()) + ssl.append( + *error->comment(), + _assembly.location() + ); + m_errorReporter.warning( + 7828_error, + _assembly.location(), + "Inline assembly has invalid NatSpec documentation.", + ssl + ); + } + + for (auto const& [tagName, tagValue]: docTags) + { + if (tagName == "solidity") + { + vector values; + boost::split(values, tagValue.content, isWhiteSpace); + + set valuesSeen; + set duplicates; + for (auto const& value: values | ranges::views::filter(not_fn(&string::empty))) + if (valuesSeen.insert(value).second) + { + if (value == "memory-safe-assembly") + _assembly.annotation().memorySafe = true; + else + m_errorReporter.warning( + 8787_error, + _assembly.location(), + "Unexpected value for @solidity tag in inline assembly: " + value + ); + } + else if (duplicates.insert(value).second) + m_errorReporter.warning( + 4377_error, + _assembly.location(), + "Value for @solidity tag in inline assembly specified multiple times: " + value + ); + } + else + m_errorReporter.warning( + 6269_error, + _assembly.location(), + "Unexpected NatSpec tag \"" + tagName + "\" with value \"" + tagValue.content + "\" in inline assembly." + ); + } + + return true; +} + void DocStringTagParser::checkParameters( CallableDeclaration const& _callable, StructurallyDocumented const& _node, diff --git a/libsolidity/analysis/DocStringTagParser.h b/libsolidity/analysis/DocStringTagParser.h index 84fde6c6c..248befcb8 100644 --- a/libsolidity/analysis/DocStringTagParser.h +++ b/libsolidity/analysis/DocStringTagParser.h @@ -48,6 +48,7 @@ private: bool visit(ModifierDefinition const& _modifier) override; bool visit(EventDefinition const& _event) override; bool visit(ErrorDefinition const& _error) override; + bool visit(InlineAssembly const& _assembly) override; void checkParameters( CallableDeclaration const& _callable, diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 53931e426..4489dce8d 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -220,6 +220,8 @@ struct InlineAssemblyAnnotation: StatementAnnotation std::map externalReferences; /// Information generated during analysis phase. std::shared_ptr analysisInfo; + /// True, if the assembly block was annotated to be memory-safe. + bool memorySafe = false; }; struct BlockAnnotation: StatementAnnotation, ScopableAnnotation diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index cf01dc4f4..ea960bb70 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -160,8 +160,8 @@ public: std::set& subObjectsCreated() { return m_subObjects; } - bool inlineAssemblySeen() const { return m_inlineAssemblySeen; } - void setInlineAssemblySeen() { m_inlineAssemblySeen = true; } + bool memoryUnsafeInlineAssemblySeen() const { return m_memoryUnsafeInlineAssemblySeen; } + void setMemoryUnsafeInlineAssemblySeen() { m_memoryUnsafeInlineAssemblySeen = true; } /// @returns the runtime ID to be used for the function in the dispatch routine /// and for internal function pointers. @@ -202,8 +202,8 @@ private: /// Whether to use checked or wrapping arithmetic. Arithmetic m_arithmetic = Arithmetic::Checked; - /// Flag indicating whether any inline assembly block was seen. - bool m_inlineAssemblySeen = false; + /// Flag indicating whether any memory-unsafe inline assembly block was seen. + bool m_memoryUnsafeInlineAssemblySeen = false; /// Function definitions queued for code generation. They're the Solidity functions whose calls /// were discovered by the IR generator during AST traversal. diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 6b52010d9..cb187b424 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -213,8 +213,8 @@ string IRGenerator::generate( t("subObjects", subObjectSources(m_context.subObjectsCreated())); // This has to be called only after all other code generation for the creation object is complete. - bool creationInvolvesAssembly = m_context.inlineAssemblySeen(); - t("memoryInitCreation", memoryInit(!creationInvolvesAssembly)); + bool creationInvolvesMemoryUnsafeAssembly = m_context.memoryUnsafeInlineAssemblySeen(); + t("memoryInitCreation", memoryInit(!creationInvolvesMemoryUnsafeAssembly)); t("useSrcMapCreation", formatUseSrcMap(m_context)); resetContext(_contract, ExecutionContext::Deployed); @@ -239,8 +239,8 @@ string IRGenerator::generate( t("useSrcMapDeployed", formatUseSrcMap(m_context)); // This has to be called only after all other code generation for the deployed object is complete. - bool deployedInvolvesAssembly = m_context.inlineAssemblySeen(); - t("memoryInitDeployed", memoryInit(!deployedInvolvesAssembly)); + bool deployedInvolvesMemoryUnsafeAssembly = m_context.memoryUnsafeInlineAssemblySeen(); + t("memoryInitDeployed", memoryInit(!deployedInvolvesMemoryUnsafeAssembly)); solAssert(_contract.annotation().creationCallGraph->get() != nullptr, ""); solAssert(_contract.annotation().deployedCallGraph->get() != nullptr, ""); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9fb73f021..cf0977c6e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2138,7 +2138,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) { setLocation(_inlineAsm); - m_context.setInlineAssemblySeen(); + if (!_inlineAsm.annotation().memorySafe) + m_context.setMemoryUnsafeInlineAssemblySeen(); CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; yul::Statement modified = bodyCopier(_inlineAsm.operations()); diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol new file mode 100644 index 000000000..3a6ccefb3 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol @@ -0,0 +1,14 @@ +contract C { + function f() public pure { + /// @test test + assembly {} + /// @solidity test + assembly {} + /// @param + assembly {} + } +} +// ---- +// Warning 6269: (60-71): Unexpected natspec tag in inline assembly: test +// Warning 8787: (95-106): Unexpected value for @solidity tag in inline assembly: test +// Warning 7828: (122-133): Inline assembly has invalid natspec documentation. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/natspec_memory_safe.sol b/test/libsolidity/syntaxTests/inlineAssembly/natspec_memory_safe.sol new file mode 100644 index 000000000..b93b20318 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/natspec_memory_safe.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure { + // @solidity memory-safe-assembly + assembly {} + } +} \ No newline at end of file From 9bcfcc61a771c3edd7e42d5ea545369415d5f22d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 10 Feb 2022 17:57:27 +0100 Subject: [PATCH 30/45] Inline assembly without memory effects is implicitly memory safe. --- libsolidity/analysis/DocStringTagParser.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 10 ++++++++-- libsolidity/ast/ASTAnnotations.h | 4 +++- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 2 +- libyul/AsmAnalysis.cpp | 1 + libyul/AsmAnalysis.h | 4 ++++ 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp index 5dc68d97f..7be9cf8df 100644 --- a/libsolidity/analysis/DocStringTagParser.cpp +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -202,7 +202,7 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly) if (valuesSeen.insert(value).second) { if (value == "memory-safe-assembly") - _assembly.annotation().memorySafe = true; + _assembly.annotation().markedMemorySafe = true; else m_errorReporter.warning( 8787_error, diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 74701bde0..955c66f84 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -763,6 +763,7 @@ void TypeChecker::endVisit(FunctionTypeName const& _funType) bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) { + bool lvalueAccessToMemoryVariable = false; // External references have already been resolved in a prior stage and stored in the annotation. // We run the resolve step again regardless. yul::ExternalIdentifierAccess::Resolver identifierAccess = [&]( @@ -787,6 +788,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) if (auto var = dynamic_cast(declaration)) { solAssert(var->type(), "Expected variable type!"); + if (_context == yul::IdentifierContext::LValue && var->type()->dataStoredIn(DataLocation::Memory)) + lvalueAccessToMemoryVariable = true; if (var->immutable()) { m_errorReporter.typeError(3773_error, nativeLocationOf(_identifier), "Assembly access to immutable variables is not supported."); @@ -974,8 +977,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) - return false; - return true; + solAssert(m_errorReporter.hasErrors()); + _inlineAssembly.annotation().hasMemoryEffects = + lvalueAccessToMemoryVariable || + (analyzer.sideEffects().memory != yul::SideEffects::None); + return false; } bool TypeChecker::visit(IfStatement const& _ifStatement) diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 4489dce8d..0d6901ef2 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -221,7 +221,9 @@ struct InlineAssemblyAnnotation: StatementAnnotation /// Information generated during analysis phase. std::shared_ptr analysisInfo; /// True, if the assembly block was annotated to be memory-safe. - bool memorySafe = false; + bool markedMemorySafe = false; + /// True, if the assembly block involves any memory opcode or assigns to variables in memory. + SetOnce hasMemoryEffects; }; struct BlockAnnotation: StatementAnnotation, ScopableAnnotation diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index cf0977c6e..263f90261 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2138,7 +2138,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) { setLocation(_inlineAsm); - if (!_inlineAsm.annotation().memorySafe) + if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe) m_context.setMemoryUnsafeInlineAssemblySeen(); CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index d19aa1a4e..c38c0ba8e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -316,6 +316,7 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) literalArguments = &f->literalArguments; validateInstructions(_funCall); + m_sideEffects += f->sideEffects; } else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ [&](Scope::Variable const&) diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index dc2770500..c71b4cbe3 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -94,6 +94,8 @@ public: void operator()(Leave const&) { } void operator()(Block const& _block); + /// @returns the worst side effects encountered during analysis (including within defined functions). + SideEffects const& sideEffects() const { return m_sideEffects; } private: /// Visits the expression, expects that it evaluates to exactly one value and /// returns the type. Reports errors on errors and returns the default type. @@ -128,6 +130,8 @@ private: /// Names of data objects to be referenced by builtin functions with literal arguments. std::set m_dataNames; ForLoop const* m_currentForLoop = nullptr; + /// Worst side effects encountered during analysis (including within defined functions). + SideEffects m_sideEffects; }; } From dfb7bf2853cfbe2f0a44f4665cbc5ed6201dbe5c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 3 Feb 2022 12:37:40 +0100 Subject: [PATCH 31/45] Report memoryguard in stack too deep error. --- libyul/backends/evm/EVMObjectCompiler.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index bede32d17..c3c95d8bc 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include @@ -74,7 +76,22 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName ); if (!stackErrors.empty()) - BOOST_THROW_EXCEPTION(stackErrors.front()); + { + vector memoryGuardCalls = FunctionCallFinder::run( + *_object.code, + "memoryguard"_yulstring + ); + auto stackError = stackErrors.front(); + string msg = stackError.comment() ? *stackError.comment() : ""; + if (memoryGuardCalls.empty()) + msg += "\nNo memoryguard was present. " + "Consider using memory-safe assembly only and annotating it via " + "\"/// @solidity memory-safe-assembly\"."; + else + msg += "\nmemoryguard was present."; + stackError << util::errinfo_comment(msg); + BOOST_THROW_EXCEPTION(stackError); + } } else { From 62a997ac97130ee63d0a60145f7035e3947d4de6 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 3 Feb 2022 16:08:32 +0100 Subject: [PATCH 32/45] Documentation. --- docs/assembly.rst | 96 ++++++++++++++++++++++++++++++++++++ docs/ir-breaking-changes.rst | 2 + 2 files changed, 98 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index e6dc6519c..b0ce0e524 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -228,6 +228,11 @@ of their block is reached. Conventions in Solidity ----------------------- +.. _assembly-typed-variables: + +Values of Typed Variables +========================= + In contrast to EVM assembly, Solidity has types which are narrower than 256 bits, e.g. ``uint24``. For efficiency, most arithmetic operations ignore the fact that types can be shorter than 256 @@ -237,6 +242,11 @@ This means that if you access such a variable from within inline assembly, you might have to manually clean the higher-order bits first. +.. _assembly-memory-management: + +Memory Management +================= + Solidity manages memory in the following way. There is a "free memory pointer" at position ``0x40`` in memory. If you want to allocate memory, use the memory starting from where this pointer points at and update it. @@ -268,3 +278,89 @@ first slot of the array and followed by the array elements. Statically-sized memory arrays do not have a length field, but it might be added later to allow better convertibility between statically- and dynamically-sized arrays, so do not rely on this. + +Memory Safety +============= + +Without the use of inline assembly, the compiler can rely on memory to remain in a well-defined +state at all times. This is especially relevant for :ref:`the new code generation pipeline via Yul IR `: +this code generation path can move local variables from stack to memory to avoid stack-too-deep errors and +perform additional memory optimizations, if it can rely on certain assumptions about memory use. + +While we recommend to always respect Solidity's memory model, inline assembly allows you to use memory +in an incompatible way. Therefore, moving stack variables to memory and additional memory optimizations are, +by default, disabled in the presence of any inline assembly block that contains a memory operation or assigns +to solidity variables in memory. + +However, you can specifically annotate an assembly block to indicate that it in fact respects Solidity's memory +model as follows: + +.. code-block:: solidity + + /// @solidity memory-safe-assembly + assembly { + ... + } + +In particular, a memory-safe assembly block may only access the following memory ranges: + +- Memory allocated by yourself using a mechanism like the ``allocate`` function described above. +- Memory allocated by Solidity, e.g. memory within the bounds of a memory array you reference. +- The scratch space between memory offset 0 and 64 mentioned above. +- Temporary memory that is located *after* the value of the free memory pointer at the beginning of the assembly block, + i.e. memory that is "allocated" at the free memory pointer without updating the free memory pointer. + +Furthermore, if the assembly block assigns to Solidity variables in memory, you need to assure that accesses to +the Solidity variables only access these memory ranges. + +Since this is mainly about the optimizer, these restrictions still need to be followed, even if the assembly block +reverts or terminates. As an example, the following assembly snippet is not memory safe: + +.. code-block:: solidity + + assembly { + returndatacopy(0, 0, returndatasize()) + revert(0, returndatasize()) + } + +But the following is: + +.. code-block:: solidity + + /// @solidity memory-safe-assembly + assembly { + let p := mload(0x40) + returndatacopy(p, 0, returndatasize()) + revert(p, returndatasize()) + } + +Note that you do not need to update the free memory pointer if there is no following allocation, +but you can only use memory starting from the current offset given by the free memory pointer. + +If the memory operations use a length of zero, it is also fine to just use any offset (not only if it falls into the scratch space): + +.. code-block:: solidity + + /// @solidity memory-safe-assembly + assembly { + revert(0, 0) + } + +Note that not only memory operations in inline assembly itself can be memory-unsafe, but also assignments to +solidity variables of reference type in memory. For example the following is not memory-safe: + +.. code-block:: solidity + + bytes memory x; + assembly { + x := 0x40 + } + x[0x20] = 0x42; + +Inline assembly that neither involves any operations that access memory nor assigns to any solidity variables +in memory is automatically considered memory-safe and does not need to be annotated. + +.. warning:: + It is your responsibility to make sure that the assembly actually satisfies the memory model. If you annotate + an assembly block as memory-safe, but violate one of the memory assumptions, this **will** lead to incorrect and + undefined behaviour that cannot easily be discovered by testing. diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index c1f6deb57..3fce53b3b 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -1,6 +1,8 @@ .. index: ir breaking changes +.. _ir-breaking-changes: + ********************************* Solidity IR-based Codegen Changes ********************************* From ad13062978beedd9960e81875ee7c9c878d78b40 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 3 Feb 2022 12:00:06 +0100 Subject: [PATCH 33/45] Patch external tests with a safe inline assembly annotation. --- test/externalTests/ens.sh | 4 +++- test/externalTests/trident.sh | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 734c5d8ae..e4edbf46c 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -48,7 +48,7 @@ function ens_test "${compile_only_presets[@]}" #ir-no-optimize # Compilation fails with "YulException: Variable var__945 is 1 slot(s) too deep inside the stack." #ir-optimize-evm-only # Compilation fails with "YulException: Variable var__945 is 1 slot(s) too deep inside the stack." - #ir-optimize-evm+yul # Compilation fails with "YulException: Variable _5 is 1 too deep in the stack [ _5 usr$i usr$h _7 usr$scratch usr$k usr$f _4 usr$len usr$j_2 RET _2 _1 var_data_mpos usr$totallen usr$x _12 ]" + ir-optimize-evm+yul # Needs memory-safe inline assembly patch legacy-optimize-evm-only legacy-optimize-evm+yul ) @@ -68,6 +68,8 @@ function ens_test replace_version_pragmas neutralize_packaged_contracts + find . -name "*.sol" -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; + for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn store_benchmark_report hardhat ens "$repo" "$preset" diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index 5e230560d..6c1f56fbb 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -56,7 +56,7 @@ function trident_test "${compile_only_presets[@]}" #ir-no-optimize # Compilation fails with: "YulException: Variable var_amount_165 is 9 slot(s) too deep inside the stack." #ir-optimize-evm-only # Compilation fails with: "YulException: Variable var_amount_165 is 9 slot(s) too deep inside the stack." - #ir-optimize-evm+yul # Compilation fails with: "YulException: Cannot swap Variable var_nearestTick with Variable _4: too deep in the stack by 4 slots" + ir-optimize-evm+yul # Needs memory-safe inline assembly patch legacy-no-optimize legacy-optimize-evm-only legacy-optimize-evm+yul @@ -87,6 +87,7 @@ function trident_test sed -i 's|uint32(-1)|type(uint32).max|g' contracts/flat/BentoBoxV1Flat.sol sed -i 's|IERC20(0)|IERC20(address(0))|g' contracts/flat/BentoBoxV1Flat.sol sed -i 's|IStrategy(0)|IStrategy(address(0))|g' contracts/flat/BentoBoxV1Flat.sol + find contracts -name "*.sol" -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; # @sushiswap/core package contains contracts that get built with 0.6.12 and fail our compiler # version check. It's not used by tests so we can remove it. From 6b6e163be5adec74d39f3f8e39739b658988381c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 10 Feb 2022 17:57:43 +0100 Subject: [PATCH 34/45] Tests. --- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 2 + .../constant_optimizer_yul/output | 11 +-- .../input.sol | 2 +- .../output | 7 +- .../input.sol | 2 +- .../output | 6 +- test/libsolidity/MemoryGuardTest.cpp | 78 +++++++++++++++++++ test/libsolidity/MemoryGuardTest.h | 53 +++++++++++++ .../constructor_safe_deploy_unsafe.sol | 17 ++++ .../constructor_unsafe_deploy_safe.sol | 17 ++++ .../memoryGuardTests/free_function.sol | 29 +++++++ .../memoryGuardTests/multi_annotation.sol | 17 ++++ .../memoryGuardTests/multiple_contracts.sol | 25 ++++++ .../safe_and_unmarked_empty.sol | 10 +++ .../safe_and_unmarked_unsafe.sol | 10 +++ test/libsolidity/memoryGuardTests/stub.sol | 4 + .../unmarked_but_no_memory_access.sol | 8 ++ .../unmarked_with_memory_access.sol | 8 ++ .../unmarked_with_memory_assignment.sol | 11 +++ .../externalContracts/prbmath_unsigned.sol | 2 +- .../inlineAssembly/invalid_natspec.sol | 4 +- .../inlineAssembly/natspec_multi.sol | 23 ++++++ .../natspec_multi_swallowed.sol | 19 +++++ test/tools/CMakeLists.txt | 1 + 25 files changed, 354 insertions(+), 14 deletions(-) create mode 100644 test/libsolidity/MemoryGuardTest.cpp create mode 100644 test/libsolidity/MemoryGuardTest.h create mode 100644 test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol create mode 100644 test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol create mode 100644 test/libsolidity/memoryGuardTests/free_function.sol create mode 100644 test/libsolidity/memoryGuardTests/multi_annotation.sol create mode 100644 test/libsolidity/memoryGuardTests/multiple_contracts.sol create mode 100644 test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol create mode 100644 test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol create mode 100644 test/libsolidity/memoryGuardTests/stub.sol create mode 100644 test/libsolidity/memoryGuardTests/unmarked_but_no_memory_access.sol create mode 100644 test/libsolidity/memoryGuardTests/unmarked_with_memory_access.sol create mode 100644 test/libsolidity/memoryGuardTests/unmarked_with_memory_assignment.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1ca9c3328..255218c15 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,6 +83,8 @@ set(libsolidity_sources libsolidity/InlineAssembly.cpp libsolidity/LibSolc.cpp libsolidity/Metadata.cpp + libsolidity/MemoryGuardTest.cpp + libsolidity/MemoryGuardTest.h libsolidity/SemanticTest.cpp libsolidity/SemanticTest.h libsolidity/SemVerMatcher.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index d8f3ef07e..d359a815a 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ Testsuite const g_interactiveTestsuites[] = { {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create}, {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create}, + {"Memory Guard Tests", "libsolidity", "memoryGuardTests", false, false, &MemoryGuardTest::create}, {"Ewasm Translation", "libyul", "ewasmTranslationTests", false, false, &yul::test::EwasmTranslationTest::create} }; diff --git a/test/cmdlineTests/constant_optimizer_yul/output b/test/cmdlineTests/constant_optimizer_yul/output index 328ac2544..2a769811a 100644 --- a/test/cmdlineTests/constant_optimizer_yul/output +++ b/test/cmdlineTests/constant_optimizer_yul/output @@ -11,14 +11,15 @@ object "C_12" { code { { /// @src 0:61:418 "contract C {..." - mstore(64, 128) + let _1 := memoryguard(0x80) + mstore(64, _1) if callvalue() { revert(0, 0) } /// @src 0:103:238 "assembly {..." sstore(0, shl(180, 1)) /// @src 0:61:418 "contract C {..." - let _1 := datasize("C_12_deployed") - codecopy(128, dataoffset("C_12_deployed"), _1) - return(128, _1) + let _2 := datasize("C_12_deployed") + codecopy(_1, dataoffset("C_12_deployed"), _2) + return(_1, _2) } } /// @use-src 0:"constant_optimizer_yul/input.sol" @@ -26,7 +27,7 @@ object "C_12" { code { { /// @src 0:61:418 "contract C {..." - mstore(64, 128) + mstore(64, memoryguard(0x80)) if callvalue() { revert(0, 0) } /// @src 0:279:410 "assembly {..." sstore(0, 0x1000000000000000000000000000000000000000000000) diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/input.sol b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/input.sol index aca9b3bef..67e1632e9 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/input.sol +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/input.sol @@ -3,6 +3,6 @@ pragma solidity >=0.0.0; pragma abicoder v2; contract D { - constructor() { assembly {}} + constructor() { assembly { mstore(0,0) } } function f() public pure {} } diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output index 34b72f8b8..d9b769a12 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output @@ -10,9 +10,12 @@ Optimized IR: object "D_12" { code { { - /// @src 0:82:161 "contract D {..." + /// @src 0:82:175 "contract D {..." mstore(64, 128) if callvalue() { revert(0, 0) } + /// @src 0:115:139 "assembly { mstore(0,0) }" + mstore(0, 0) + /// @src 0:82:175 "contract D {..." let _1 := datasize("D_12_deployed") codecopy(128, dataoffset("D_12_deployed"), _1) return(128, _1) @@ -22,7 +25,7 @@ object "D_12" { object "D_12_deployed" { code { { - /// @src 0:82:161 "contract D {..." + /// @src 0:82:175 "contract D {..." let _1 := memoryguard(0x80) mstore(64, _1) if iszero(lt(calldatasize(), 4)) diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/input.sol b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/input.sol index e217f9cbb..26c0bfa98 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/input.sol +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/input.sol @@ -4,6 +4,6 @@ pragma abicoder v2; contract D { function f() public pure { - assembly {} + assembly { mstore(0,0) } } } diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output index cc95451e6..9a07c7861 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output @@ -10,7 +10,7 @@ Optimized IR: object "D_8" { code { { - /// @src 0:82:153 "contract D {..." + /// @src 0:82:166 "contract D {..." let _1 := memoryguard(0x80) mstore(64, _1) if callvalue() { revert(0, 0) } @@ -23,7 +23,7 @@ object "D_8" { object "D_8_deployed" { code { { - /// @src 0:82:153 "contract D {..." + /// @src 0:82:166 "contract D {..." mstore(64, 128) if iszero(lt(calldatasize(), 4)) { @@ -32,6 +32,8 @@ object "D_8" { { if callvalue() { revert(_1, _1) } if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + /// @src 0:134:158 "assembly { mstore(0,0) }" + mstore(/** @src 0:82:166 "contract D {..." */ _1, _1) return(128, _1) } } diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp new file mode 100644 index 000000000..b757e673f --- /dev/null +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -0,0 +1,78 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace solidity; +using namespace solidity::util; +using namespace solidity::util::formatting; +using namespace solidity::langutil; +using namespace solidity::frontend; +using namespace solidity::frontend::test; +using namespace yul; + +TestCase::TestResult MemoryGuardTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) +{ + compiler().reset(); + compiler().setSources(StringMap{{"", m_source}}); + compiler().setViaIR(true); + compiler().setOptimiserSettings(OptimiserSettings::none()); + if (!compiler().compile()) + return TestResult::FatalError; + + m_obtainedResult.clear(); + for (string contractName: compiler().contractNames()) + { + ErrorList errors; + auto [object, analysisInfo] = yul::test::parse( + compiler().yulIR(contractName), + EVMDialect::strictAssemblyForEVMObjects({}), + errors + ); + + if (!object || !analysisInfo || Error::containsErrors(errors)) + { + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing IR." << endl; + return TestResult::FatalError; + } + + auto handleObject = [&](std::string const& _kind, Object const& _object) { + m_obtainedResult += contractName + "(" + _kind + ") " + (FunctionCallFinder::run( + *_object.code, + "memoryguard"_yulstring + ).empty() ? "false" : "true") + "\n"; + }; + handleObject("creation", *object); + size_t deployedIndex = object->subIndexByName.at( + YulString(IRNames::deployedObject(compiler().contractDefinition(contractName))) + ); + handleObject("runtime", dynamic_cast(*object->subObjects[deployedIndex])); + } + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libsolidity/MemoryGuardTest.h b/test/libsolidity/MemoryGuardTest.h new file mode 100644 index 000000000..e2ca8a6e5 --- /dev/null +++ b/test/libsolidity/MemoryGuardTest.h @@ -0,0 +1,53 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace solidity::frontend::test +{ + +using solidity::test::SyntaxTestError; + +class MemoryGuardTest: public AnalysisFramework, public TestCase +{ +public: + static std::unique_ptr create(Config const& _config) + { + return std::make_unique(_config.filename); + } + MemoryGuardTest(std::string const& _filename): TestCase(_filename) + { + m_source = m_reader.source(); + m_expectation = m_reader.simpleExpectations(); + } + + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override; +}; + +} diff --git a/test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol b/test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol new file mode 100644 index 000000000..2ab905ad8 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol @@ -0,0 +1,17 @@ +contract C { + constructor() { + uint256 x; + assembly { x := 0 } + f(); + } + function f() internal pure { + /// @solidity memory-safe-assembly + assembly { mstore(0, 0) } + } + function g() public pure { + assembly { mstore(0, 0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol b/test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol new file mode 100644 index 000000000..12b7e772f --- /dev/null +++ b/test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol @@ -0,0 +1,17 @@ +contract C { + constructor() { + uint256 x; + assembly { x := 0 } + f(); + } + function f() internal pure { + assembly { mstore(0, 0) } + } + function g() public pure { + /// @solidity memory-safe-assembly + assembly { mstore(0, 0) } + } +} +// ---- +// :C(creation) false +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/free_function.sol b/test/libsolidity/memoryGuardTests/free_function.sol new file mode 100644 index 000000000..a417189ed --- /dev/null +++ b/test/libsolidity/memoryGuardTests/free_function.sol @@ -0,0 +1,29 @@ +function safe() pure returns (uint256 x) { + assembly { x := 42 } + /// @solidity memory-safe-assembly + assembly { mstore(0, 0) } +} +function unsafe() pure returns (uint256 x) { + assembly { pop(mload(0)) } +} +contract C { + constructor() { + unsafe(); + } + function f() public pure { + safe(); + } +} +contract D { + constructor() { + safe(); + } + function f() public pure { + unsafe(); + } +} +// ---- +// :C(creation) false +// :C(runtime) true +// :D(creation) true +// :D(runtime) false diff --git a/test/libsolidity/memoryGuardTests/multi_annotation.sol b/test/libsolidity/memoryGuardTests/multi_annotation.sol new file mode 100644 index 000000000..478546b83 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/multi_annotation.sol @@ -0,0 +1,17 @@ +contract C { + constructor() { + /// @solidity memory-safe-assembly a memory-safe-assembly + assembly { mstore(0, 0) } + } + function f() internal pure { + /// @solidity a memory-safe-assembly + assembly { mstore(0, 0) } + /// @solidity a + /// memory-safe-assembly + /// b + assembly { mstore(0, 0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/multiple_contracts.sol b/test/libsolidity/memoryGuardTests/multiple_contracts.sol new file mode 100644 index 000000000..84d2cb453 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/multiple_contracts.sol @@ -0,0 +1,25 @@ +contract C { + constructor(uint256 x) { + assembly { x := 4 } + /// @solidity memory-safe-assembly + assembly { mstore(0, 0) } + } + function f() public pure { + assembly { mstore(0,0) } + } +} +contract D { + constructor() { + assembly { mstore(0,0) } + } + function f(uint256 x) public pure { + assembly { x := 4 } + /// @solidity memory-safe-assembly + assembly { mstore(0, 0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false +// :D(creation) false +// :D(runtime) true diff --git a/test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol b/test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol new file mode 100644 index 000000000..614201deb --- /dev/null +++ b/test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol @@ -0,0 +1,10 @@ +contract C { + function f() external pure { + /// @solidity memory-safe-assembly + assembly {} + assembly {} + } +} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol b/test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol new file mode 100644 index 000000000..32d19993c --- /dev/null +++ b/test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol @@ -0,0 +1,10 @@ +contract C { + function f() external pure { + /// @solidity memory-safe-assembly + assembly {} + assembly { mstore(0,0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/memoryGuardTests/stub.sol b/test/libsolidity/memoryGuardTests/stub.sol new file mode 100644 index 000000000..65f6447c1 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/stub.sol @@ -0,0 +1,4 @@ +contract C {} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/unmarked_but_no_memory_access.sol b/test/libsolidity/memoryGuardTests/unmarked_but_no_memory_access.sol new file mode 100644 index 000000000..8af88d75d --- /dev/null +++ b/test/libsolidity/memoryGuardTests/unmarked_but_no_memory_access.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint256 x, uint256 y) public pure returns (uint256 z){ + assembly { z := add(x, y) } + } +} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/unmarked_with_memory_access.sol b/test/libsolidity/memoryGuardTests/unmarked_with_memory_access.sol new file mode 100644 index 000000000..88f826fdb --- /dev/null +++ b/test/libsolidity/memoryGuardTests/unmarked_with_memory_access.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + assembly { mstore(0,0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/memoryGuardTests/unmarked_with_memory_assignment.sol b/test/libsolidity/memoryGuardTests/unmarked_with_memory_assignment.sol new file mode 100644 index 000000000..c7519a65e --- /dev/null +++ b/test/libsolidity/memoryGuardTests/unmarked_with_memory_assignment.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + bytes memory x; + assembly { + x := 0 + } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 720f57489..0488179f1 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -50,7 +50,7 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1790188 +// gas irOptimized: 1792108 // gas legacy: 2250130 // gas legacyOptimized: 1746528 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol index 3a6ccefb3..d23eceeed 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid_natspec.sol @@ -9,6 +9,6 @@ contract C { } } // ---- -// Warning 6269: (60-71): Unexpected natspec tag in inline assembly: test +// Warning 6269: (60-71): Unexpected NatSpec tag "test" with value "test" in inline assembly. // Warning 8787: (95-106): Unexpected value for @solidity tag in inline assembly: test -// Warning 7828: (122-133): Inline assembly has invalid natspec documentation. +// Warning 7828: (122-133): Inline assembly has invalid NatSpec documentation. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol new file mode 100644 index 000000000..945d62b06 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol @@ -0,0 +1,23 @@ +function f() pure { + /// @unrelated bogus-value + + /// @before bogus-value + /// + /// @solidity a memory-safe-assembly b c + /// d + /// @after bogus-value + assembly {} + /// @solidity memory-safe-assembly a a a + /// memory-safe-assembly + assembly {} +} +// ---- +// Warning 6269: (189-200): Unexpected NatSpec tag "after" with value "bogus-value" in inline assembly. +// Warning 6269: (189-200): Unexpected NatSpec tag "before" with value "bogus-value" in inline assembly. +// Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: a +// Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: b +// Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: c +// Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: d +// Warning 8787: (289-300): Unexpected value for @solidity tag in inline assembly: a +// Warning 4377: (289-300): Value for @solidity tag in inline assembly specified multiple times: a +// Warning 4377: (289-300): Value for @solidity tag in inline assembly specified multiple times: memory-safe-assembly diff --git a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol new file mode 100644 index 000000000..74be1232d --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol @@ -0,0 +1,19 @@ +function f() pure { + /// @unrelated bogus-value + + /// @before + /// + /// @solidity a memory-safe-assembly b c + /// d + /// @after bogus-value + assembly {} + /// @solidity memory-safe-assembly a a a + /// memory-safe-assembly + assembly {} +} +// ---- +// Warning 6269: (177-188): Unexpected NatSpec tag "after" with value "bogus-value" in inline assembly. +// Warning 6269: (177-188): Unexpected NatSpec tag "before" with value "@solidity a memory-safe-assembly b c d" in inline assembly. +// Warning 8787: (277-288): Unexpected value for @solidity tag in inline assembly: a +// Warning 4377: (277-288): Value for @solidity tag in inline assembly specified multiple times: a +// Warning 4377: (277-288): Value for @solidity tag in inline assembly specified multiple times: memory-safe-assembly diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 18e3d4377..5971341ec 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(isoltest ../libsolidity/util/TestFileParser.cpp ../libsolidity/util/TestFunctionCall.cpp ../libsolidity/GasTest.cpp + ../libsolidity/MemoryGuardTest.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/SemanticTest.cpp ../libsolidity/AnalysisFramework.cpp From 30008465bf095291b4ea222a9e5c77a97eb28ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 2 Mar 2022 16:47:55 +0100 Subject: [PATCH 35/45] perpetual-pools: Use Hardhat 2.8.4 to work around @openzeppelin/hardhat-upgrades's problem with parallel compilation on Hardhat 2.9.0 --- test/externalTests/perpetual-pools.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index 8f90ed0b4..7e4289698 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -66,6 +66,11 @@ function perpetual_pools_test force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn install + # The project depends on @openzeppelin/hardhat-upgrades, which is currently not prepared + # for the parallel compilation introduced in Hardhat 2.9.0. + # TODO: Remove when https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/528 is fixed. + yarn add hardhat@2.8.4 + replace_version_pragmas for preset in $SELECTED_PRESETS; do From 290b1c3a90c1e2cceb6b33ab9ed8e9c4f11ac46c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 14 Feb 2022 13:21:15 +0100 Subject: [PATCH 36/45] Allow memory-safe inline assembly dialect flag. --- libsolidity/analysis/DocStringTagParser.cpp | 10 ++++++++++ libsolidity/analysis/SyntaxChecker.cpp | 21 +++++++++++++++++++++ libsolidity/ast/AST.h | 9 ++++++++- libsolidity/ast/ASTJsonConverter.cpp | 16 ++++++++++++++-- libsolidity/ast/ASTJsonImporter.cpp | 13 +++++++++++++ libsolidity/parsing/Parser.cpp | 17 ++++++++++++++++- 6 files changed, 82 insertions(+), 4 deletions(-) diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp index 7be9cf8df..1dc2711ef 100644 --- a/libsolidity/analysis/DocStringTagParser.cpp +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -202,7 +202,17 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly) if (valuesSeen.insert(value).second) { if (value == "memory-safe-assembly") + { + if (_assembly.annotation().markedMemorySafe) + m_errorReporter.warning( + 8544_error, + _assembly.location(), + "Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. " + "If you are not concerned with backwards compatibility, only use the assembly flag, " + "otherwise only use the NatSpec tag." + ); _assembly.annotation().markedMemorySafe = true; + } else m_errorReporter.warning( 8787_error, diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index e47080cb4..589787a89 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -334,6 +334,27 @@ bool SyntaxChecker::visit(UnaryOperation const& _operation) bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) { + if (_inlineAssembly.flags()) + for (auto flag: *_inlineAssembly.flags()) + { + if (*flag == "memory-safe") + { + if (_inlineAssembly.annotation().markedMemorySafe) + m_errorReporter.syntaxError( + 7026_error, + _inlineAssembly.location(), + "Inline assembly marked memory-safe multiple times." + ); + _inlineAssembly.annotation().markedMemorySafe = true; + } + else + m_errorReporter.warning( + 4430_error, + _inlineAssembly.location(), + "Unknown inline assembly flag: \"" + *flag + "\"" + ); + } + if (!m_useYulOptimizer) return false; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index c35c69c9d..4893c212f 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1463,19 +1463,26 @@ public: SourceLocation const& _location, ASTPointer const& _docString, yul::Dialect const& _dialect, + ASTPointer>> _flags, std::shared_ptr _operations ): - Statement(_id, _location, _docString), m_dialect(_dialect), m_operations(std::move(_operations)) {} + Statement(_id, _location, _docString), + m_dialect(_dialect), + m_flags(move(_flags)), + m_operations(std::move(_operations)) + {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; yul::Dialect const& dialect() const { return m_dialect; } yul::Block const& operations() const { return *m_operations; } + ASTPointer>> const& flags() const { return m_flags; } InlineAssemblyAnnotation& annotation() const override; private: yul::Dialect const& m_dialect; + ASTPointer>> m_flags; std::shared_ptr m_operations; }; diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 97417f81c..6b48797d1 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -600,11 +600,23 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node) for (Json::Value& it: externalReferences | ranges::views::values) externalReferencesJson.append(std::move(it)); - setJsonNode(_node, "InlineAssembly", { + std::vector> attributes = { make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), make_pair("externalReferences", std::move(externalReferencesJson)), make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) - }); + }; + + if (_node.flags()) + { + Json::Value flags(Json::arrayValue); + for (auto const& flag: *_node.flags()) + if (flag) + flags.append(*flag); + else + flags.append(Json::nullValue); + attributes.emplace_back(make_pair("flags", move(flags))); + } + setJsonNode(_node, "InlineAssembly", move(attributes)); return false; } diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 2e69df93f..d71864f34 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -626,11 +626,24 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json::Value con astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!"); yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value()); + ASTPointer>> flags; + if (_node.isMember("flags")) + { + flags = make_shared>>(); + Json::Value const& flagsNode = _node["flags"]; + astAssert(flagsNode.isArray(), "Assembly flags must be an array."); + for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i) + { + astAssert(flagsNode[i].isString(), "Assembly flag must be a string."); + flags->emplace_back(make_shared(flagsNode[i].asString())); + } + } shared_ptr operations = make_shared(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); return createASTNode( _node, nullOrASTString(_node, "documentation"), dialect, + move(flags), operations ); } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index fea062d01..b1d7e7cca 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1321,13 +1321,28 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con advance(); } + ASTPointer>> flags; + if (m_scanner->currentToken() == Token::LParen) + { + flags = make_shared>>(); + do + { + advance(); + expectToken(Token::StringLiteral, false); + flags->emplace_back(make_shared(m_scanner->currentLiteral())); + advance(); + } + while (m_scanner->currentToken() == Token::Comma); + expectToken(Token::RParen); + } + yul::Parser asmParser(m_errorReporter, dialect); shared_ptr block = asmParser.parseInline(m_scanner); if (block == nullptr) BOOST_THROW_EXCEPTION(FatalError()); location.end = nativeLocationOf(*block).end; - return make_shared(nextID(), location, _docString, dialect, block); + return make_shared(nextID(), location, _docString, dialect, move(flags), block); } ASTPointer Parser::parseIfStatement(ASTPointer const& _docString) From 93dd8ad5530eddada38d35c612d70a29b4fa5e8e Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 14 Feb 2022 13:21:00 +0100 Subject: [PATCH 37/45] Tests. --- .../constructor_safe_deploy_unsafe.sol | 0 .../constructor_unsafe_deploy_safe.sol | 0 .../{ => comment}/free_function.sol | 0 .../{ => comment}/multi_annotation.sol | 0 .../{ => comment}/multiple_contracts.sol | 0 .../{ => comment}/safe_and_unmarked_empty.sol | 0 .../safe_and_unmarked_unsafe.sol | 0 .../constructor_safe_deploy_unsafe.sol | 17 +++++++++++ .../constructor_unsafe_deploy_safe.sol | 16 +++++++++++ .../dialectString/free_function.sol | 28 +++++++++++++++++++ .../dialectString/multiple_contracts.sol | 23 +++++++++++++++ .../dialectString/safe_and_unmarked_empty.sol | 9 ++++++ .../safe_and_unmarked_unsafe.sol | 9 ++++++ .../memoryGuardTests/dialectString/stub.sol | 4 +++ .../assembly_dialect_duplicate_option.sol | 5 ++++ .../assembly_dialect_invalid_options.sol | 8 ++++++ .../assembly_dialect_leading_space.sol | 5 ++++ .../assembly_duplicate_option.sol | 5 ++++ .../assembly_empty_option_list.sol | 5 ++++ .../assembly_empty_option_list_dialect.sol | 5 ++++ .../assembly_flags_delimiter.sol | 5 ++++ .../assembly_invalid_options.sol | 8 ++++++ ...memory_safe_dialect_string_and_comment.sol | 7 +++++ .../memory_safe_in_dialect_string.sol | 3 ++ 24 files changed, 162 insertions(+) rename test/libsolidity/memoryGuardTests/{ => comment}/constructor_safe_deploy_unsafe.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/constructor_unsafe_deploy_safe.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/free_function.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/multi_annotation.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/multiple_contracts.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/safe_and_unmarked_empty.sol (100%) rename test/libsolidity/memoryGuardTests/{ => comment}/safe_and_unmarked_unsafe.sol (100%) create mode 100644 test/libsolidity/memoryGuardTests/dialectString/constructor_safe_deploy_unsafe.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/constructor_unsafe_deploy_safe.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/free_function.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/multiple_contracts.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_empty.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_unsafe.sol create mode 100644 test/libsolidity/memoryGuardTests/dialectString/stub.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_duplicate_option.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_invalid_options.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_leading_space.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_duplicate_option.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list_dialect.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_flags_delimiter.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/assembly_invalid_options.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/memory_safe_in_dialect_string.sol diff --git a/test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol b/test/libsolidity/memoryGuardTests/comment/constructor_safe_deploy_unsafe.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/constructor_safe_deploy_unsafe.sol rename to test/libsolidity/memoryGuardTests/comment/constructor_safe_deploy_unsafe.sol diff --git a/test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol b/test/libsolidity/memoryGuardTests/comment/constructor_unsafe_deploy_safe.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/constructor_unsafe_deploy_safe.sol rename to test/libsolidity/memoryGuardTests/comment/constructor_unsafe_deploy_safe.sol diff --git a/test/libsolidity/memoryGuardTests/free_function.sol b/test/libsolidity/memoryGuardTests/comment/free_function.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/free_function.sol rename to test/libsolidity/memoryGuardTests/comment/free_function.sol diff --git a/test/libsolidity/memoryGuardTests/multi_annotation.sol b/test/libsolidity/memoryGuardTests/comment/multi_annotation.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/multi_annotation.sol rename to test/libsolidity/memoryGuardTests/comment/multi_annotation.sol diff --git a/test/libsolidity/memoryGuardTests/multiple_contracts.sol b/test/libsolidity/memoryGuardTests/comment/multiple_contracts.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/multiple_contracts.sol rename to test/libsolidity/memoryGuardTests/comment/multiple_contracts.sol diff --git a/test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol b/test/libsolidity/memoryGuardTests/comment/safe_and_unmarked_empty.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/safe_and_unmarked_empty.sol rename to test/libsolidity/memoryGuardTests/comment/safe_and_unmarked_empty.sol diff --git a/test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol b/test/libsolidity/memoryGuardTests/comment/safe_and_unmarked_unsafe.sol similarity index 100% rename from test/libsolidity/memoryGuardTests/safe_and_unmarked_unsafe.sol rename to test/libsolidity/memoryGuardTests/comment/safe_and_unmarked_unsafe.sol diff --git a/test/libsolidity/memoryGuardTests/dialectString/constructor_safe_deploy_unsafe.sol b/test/libsolidity/memoryGuardTests/dialectString/constructor_safe_deploy_unsafe.sol new file mode 100644 index 000000000..8c5aa229d --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/constructor_safe_deploy_unsafe.sol @@ -0,0 +1,17 @@ +contract C { + constructor() { + uint256 x; + assembly { x := 0 } + f(); + } + function f() internal pure { + assembly "evmasm" ("memory-safe") { mstore(0, 0) } + assembly ("memory-safe") { mstore(0, 0) } + } + function g() public pure { + assembly { mstore(0, 0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/memoryGuardTests/dialectString/constructor_unsafe_deploy_safe.sol b/test/libsolidity/memoryGuardTests/dialectString/constructor_unsafe_deploy_safe.sol new file mode 100644 index 000000000..595e25914 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/constructor_unsafe_deploy_safe.sol @@ -0,0 +1,16 @@ +contract C { + constructor() { + uint256 x; + assembly { x := 0 } + f(); + } + function f() internal pure { + assembly { mstore(0, 0) } + } + function g() public pure { + assembly "evmasm" ("memory-safe") { mstore(0, 0) } + } +} +// ---- +// :C(creation) false +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/dialectString/free_function.sol b/test/libsolidity/memoryGuardTests/dialectString/free_function.sol new file mode 100644 index 000000000..9e3d2a4b5 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/free_function.sol @@ -0,0 +1,28 @@ +function safe() pure returns (uint256 x) { + assembly { x := 42 } + assembly "evmasm" ("memory-safe") { mstore(0, 0) } +} +function unsafe() pure returns (uint256 x) { + assembly { pop(mload(0)) } +} +contract C { + constructor() { + unsafe(); + } + function f() public pure { + safe(); + } +} +contract D { + constructor() { + safe(); + } + function f() public pure { + unsafe(); + } +} +// ---- +// :C(creation) false +// :C(runtime) true +// :D(creation) true +// :D(runtime) false diff --git a/test/libsolidity/memoryGuardTests/dialectString/multiple_contracts.sol b/test/libsolidity/memoryGuardTests/dialectString/multiple_contracts.sol new file mode 100644 index 000000000..2ee227bc6 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/multiple_contracts.sol @@ -0,0 +1,23 @@ +contract C { + constructor(uint256 x) { + assembly { x := 4 } + assembly "evmasm" ("memory-safe") { mstore(0, 0) } + } + function f() public pure { + assembly { mstore(0,0) } + } +} +contract D { + constructor() { + assembly { mstore(0,0) } + } + function f(uint256 x) public pure { + assembly { x := 4 } + assembly ("memory-safe") { mstore(0, 0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false +// :D(creation) false +// :D(runtime) true diff --git a/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_empty.sol b/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_empty.sol new file mode 100644 index 000000000..ab653be97 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_empty.sol @@ -0,0 +1,9 @@ +contract C { + function f() external pure { + assembly "evmasm" ("memory-safe") {} + assembly {} + } +} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_unsafe.sol b/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_unsafe.sol new file mode 100644 index 000000000..8b865d5b8 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/safe_and_unmarked_unsafe.sol @@ -0,0 +1,9 @@ +contract C { + function f() external pure { + assembly "evmasm" ("memory-safe") {} + assembly { mstore(0,0) } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/memoryGuardTests/dialectString/stub.sol b/test/libsolidity/memoryGuardTests/dialectString/stub.sol new file mode 100644 index 000000000..65f6447c1 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/dialectString/stub.sol @@ -0,0 +1,4 @@ +contract C {} +// ---- +// :C(creation) true +// :C(runtime) true diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_duplicate_option.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_duplicate_option.sol new file mode 100644 index 000000000..7e0672f65 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_duplicate_option.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly "evmasm" ("memory-safe", "memory-safe") {} +} +// ---- +// SyntaxError 7026: (24-75): Inline assembly marked memory-safe multiple times. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_invalid_options.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_invalid_options.sol new file mode 100644 index 000000000..44206c9ec --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_invalid_options.sol @@ -0,0 +1,8 @@ +function f() pure { + assembly "evmasm" ("a", "b", "c", "c") {} +} +// ---- +// Warning 4430: (24-65): Unknown inline assembly flag: "a" +// Warning 4430: (24-65): Unknown inline assembly flag: "b" +// Warning 4430: (24-65): Unknown inline assembly flag: "c" +// Warning 4430: (24-65): Unknown inline assembly flag: "c" diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_leading_space.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_leading_space.sol new file mode 100644 index 000000000..1cf1e7fb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_dialect_leading_space.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly " evmasm" {} +} +// ---- +// ParserError 4531: (33-42): Only "evmasm" supported. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_duplicate_option.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_duplicate_option.sol new file mode 100644 index 000000000..69c503559 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_duplicate_option.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly ("memory-safe", "memory-safe") {} +} +// ---- +// SyntaxError 7026: (24-66): Inline assembly marked memory-safe multiple times. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list.sol new file mode 100644 index 000000000..cae17320b --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly () {} +} +// ---- +// ParserError 2314: (34-35): Expected 'StringLiteral' but got ')' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list_dialect.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list_dialect.sol new file mode 100644 index 000000000..222e59b93 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_empty_option_list_dialect.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly "evmasm" () {} +} +// ---- +// ParserError 2314: (43-44): Expected 'StringLiteral' but got ')' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_flags_delimiter.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_flags_delimiter.sol new file mode 100644 index 000000000..cd82f8aaa --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_flags_delimiter.sol @@ -0,0 +1,5 @@ +function f() pure { + assembly ("a" "b") {} +} +// ---- +// ParserError 2314: (35-38): Expected ')' but got 'StringLiteral' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assembly_invalid_options.sol b/test/libsolidity/syntaxTests/inlineAssembly/assembly_invalid_options.sol new file mode 100644 index 000000000..3364d793e --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assembly_invalid_options.sol @@ -0,0 +1,8 @@ +function f() pure { + assembly ("a", "b", "c", "c") {} +} +// ---- +// Warning 4430: (24-56): Unknown inline assembly flag: "a" +// Warning 4430: (24-56): Unknown inline assembly flag: "b" +// Warning 4430: (24-56): Unknown inline assembly flag: "c" +// Warning 4430: (24-56): Unknown inline assembly flag: "c" diff --git a/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol new file mode 100644 index 000000000..9d0fd3e1c --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol @@ -0,0 +1,7 @@ +function f() pure { + /// @solidity memory-safe-assembly + assembly "evmasm" ("memory-safe") { + } +} +// ---- +// Warning 8544: (63-104): Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. If you are not concerned with backwards compatibility, only use the assembly flag, otherwise only use the NatSpec tag. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_in_dialect_string.sol b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_in_dialect_string.sol new file mode 100644 index 000000000..c034f803d --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_in_dialect_string.sol @@ -0,0 +1,3 @@ +function f() pure { + assembly "evmasm" ("memory-safe") {} +} \ No newline at end of file From 0381de54c2aaf1575ef93d77974f1d58c25789aa Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 14 Feb 2022 13:23:50 +0100 Subject: [PATCH 38/45] Update docs. --- docs/assembly.rst | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index b0ce0e524..746da43c1 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -297,8 +297,7 @@ model as follows: .. code-block:: solidity - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { ... } @@ -327,8 +326,7 @@ But the following is: .. code-block:: solidity - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { let p := mload(0x40) returndatacopy(p, 0, returndatasize()) revert(p, returndatasize()) @@ -341,8 +339,7 @@ If the memory operations use a length of zero, it is also fine to just use any o .. code-block:: solidity - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { revert(0, 0) } @@ -364,3 +361,16 @@ in memory is automatically considered memory-safe and does not need to be annota It is your responsibility to make sure that the assembly actually satisfies the memory model. If you annotate an assembly block as memory-safe, but violate one of the memory assumptions, this **will** lead to incorrect and undefined behaviour that cannot easily be discovered by testing. + +In case you are developing a library that is meant to be compatible across multiple versions +of solidity, you can use a special comment to annotate an assembly block as memory-safe: + +.. code-block:: solidity + + /// @solidity memory-safe-assembly + assembly { + ... + } + +Note that we will disallow the annotation via comment in a future breaking release, so if you are not concerned with +backwards-compatibility with older compiler versions, prefer using the dialect string. From 46d8611e90f9ffd9764db5f3b9c16a5139c0eb61 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 14 Feb 2022 13:57:56 +0100 Subject: [PATCH 39/45] Adjust grammar. --- docs/grammar/SolidityLexer.g4 | 6 ++++++ docs/grammar/SolidityParser.g4 | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index 5a73be85f..653255ae3 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -251,6 +251,12 @@ mode AssemblyBlockMode; AssemblyDialect: '"evmasm"'; AssemblyLBrace: '{' -> popMode, pushMode(YulMode); +AssemblyFlagString: '"' DoubleQuotedStringCharacter+ '"'; + +AssemblyBlockLParen: '('; +AssemblyBlockRParen: ')'; +AssemblyBlockComma: ','; + AssemblyBlockWS: [ \t\r\n\u000C]+ -> skip ; AssemblyBlockCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; AssemblyBlockLINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN) ; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 110773fed..e41bb2ba9 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -476,7 +476,13 @@ revertStatement: Revert expression callArgumentList Semicolon; * The contents of an inline assembly block use a separate scanner/lexer, i.e. the set of keywords and * allowed identifiers is different inside an inline assembly block. */ -assemblyStatement: Assembly AssemblyDialect? AssemblyLBrace yulStatement* YulRBrace; +assemblyStatement: Assembly AssemblyDialect? assemblyFlags? AssemblyLBrace yulStatement* YulRBrace; + +/** + * Assembly flags. + * Comma-separated list of double-quoted strings as flags. + */ +assemblyFlags: AssemblyBlockLParen AssemblyFlagString (AssemblyBlockComma AssemblyFlagString)* AssemblyBlockRParen; //@doc:inline variableDeclarationList: variableDeclarations+=variableDeclaration (Comma variableDeclarations+=variableDeclaration)*; From ab0ab4491da2c9d92e6bc8dd9ee2832a6ec2f9b0 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 1 Mar 2022 17:40:27 -0500 Subject: [PATCH 40/45] Update CI to use new buildpacks. --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b50f7583..65e7113a3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,16 +9,16 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-10 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:e61939751ff9777307857361f712b581bfc8a8aaae75fab7b50febc764710587" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-11 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:9928dc357829e475e8729c62a1c2d495dbb41cb9fe4c4b115a5568be8e1ed69e" ubuntu-2004-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-10 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:0de8c68f084120b2a165406e3a0c2aab58b32f5b7182c2322245245f1d243b8d" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-11 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:72fb9574c90e8ef908dce4c9dd9788ff4de708b504d970cd9146eed8911c313e" ubuntu-1604-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-15 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:87f1a57586eec194a6217ab624efc69d3d9af2f7ac8ca36497ad57488c2f08ae" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-16 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:fe54d8e5409827d43edb0dc8ad0d9e4232a675050ceb271c873b73e5ee267938" emscripten-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:emscripten-9 From beabc51c206da9ec9fb28edcb9d554b97099b432 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Wed, 16 Feb 2022 17:33:39 +0530 Subject: [PATCH 41/45] returnSize assigned according to truth value of returnInfo.dynamicReturnSize --- libsolidity/codegen/ReturnInfo.cpp | 2 + .../codegen/ir/IRGeneratorForStatements.cpp | 38 +++--- .../output.json | 128 +++++++++++------- .../output.json | 40 ++++-- .../abi_encode_calldata_slice.sol | 4 +- .../struct/struct_storage_ptr.sol | 2 +- .../abi_encode_calldata_slice.sol | 4 +- ...2_in_function_inherited_in_v1_contract.sol | 2 +- .../abiEncoderV2/calldata_array.sol | 2 +- .../array/fixed_arrays_as_return_type.sol | 2 +- .../array/function_array_cross_calls.sol | 2 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../constructor/arrays_in_constructors.sol | 2 +- .../bytes_in_constructors_packer.sol | 2 +- .../events/event_emit_from_other_contract.sol | 2 +- .../creation_function_call_with_args.sol | 2 +- .../creation_function_call_with_salt.sol | 2 +- .../external_call_to_nonexisting.sol | 2 +- ...ernal_call_to_nonexisting_debugstrings.sol | 2 +- .../functionCall/failed_create.sol | 4 +- .../functionCall/gas_and_value_basic.sol | 2 +- .../gas_and_value_brace_syntax.sol | 2 +- .../return_size_bigger_than_expected.sol | 31 +++++ .../return_size_shorter_than_expected.sol | 32 +++++ ...n_expected_evm_version_after_homestead.sol | 34 +++++ .../immutable/multi_creation.sol | 2 +- ...ted_function_calldata_memory_interface.sol | 2 +- .../inheritance/value_for_constructor.sol | 2 +- .../balance_other_contract.sol | 2 +- .../libraries/internal_types_in_library.sol | 2 +- .../using_library_mappings_public.sol | 2 +- .../using_library_mappings_return.sol | 2 +- .../libraries/using_library_structs.sol | 2 +- .../salted_create_with_value.sol | 2 +- .../userDefinedValueType/calldata.sol | 2 +- .../semanticTests/various/senders_balance.sol | 2 +- .../skip_dynamic_types_for_structs.sol | 2 +- .../semanticTests/various/value_complex.sol | 2 +- .../semanticTests/various/value_insane.sol | 2 +- .../viaYul/copy_struct_invalid_ir_bug.sol | 2 +- 40 files changed, 261 insertions(+), 116 deletions(-) create mode 100644 test/libsolidity/semanticTests/functionCall/return_size_bigger_than_expected.sol create mode 100644 test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected.sol create mode 100644 test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected_evm_version_after_homestead.sol diff --git a/libsolidity/codegen/ReturnInfo.cpp b/libsolidity/codegen/ReturnInfo.cpp index fd2ff451f..28518d9b2 100644 --- a/libsolidity/codegen/ReturnInfo.cpp +++ b/libsolidity/codegen/ReturnInfo.cpp @@ -54,4 +54,6 @@ ReturnInfo::ReturnInfo(EVMVersion const& _evmVersion, FunctionType const& _funct estimatedReturnSize += retType->decodingType()->calldataEncodedSize(); } } + if (dynamicReturnSize) + solAssert(estimatedReturnSize == 0); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9fb73f021..ed49c94b0 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2505,6 +2505,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall( appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; } + // NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically. + // When it's dynamic, we get zero from estimatedReturnSize() instead and then we need an explicit returndatacopy(). Whiskers templ(R"( if iszero(extcodesize(
)) { () } @@ -2514,22 +2516,29 @@ void IRGeneratorForStatements::appendExternalFunctionCall( mstore(, ()) let := (add(, 4) ) - let := (,
, , , sub(, ), , ) + let := (,
, , , sub(, ), , ) if iszero() { () } let if { - - // copy dynamic return data out - returndatacopy(, 0, returndatasize()) - + + let := returndatasize() + returndatacopy(, 0, ) + + let := + + if gt(, returndatasize()) { + := returndatasize() + } + + // update freeMemoryPointer according to dynamic return size - (, ) + (, ) // decode return parameters from external try-call into retVars - := (, add(, )) + := (, add(, )) } )"); templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code")); @@ -2558,21 +2567,18 @@ void IRGeneratorForStatements::appendExternalFunctionCall( templ("funSel", IRVariable(_functionCall.expression()).part("functionSelector").name()); templ("address", IRVariable(_functionCall.expression()).part("address").name()); - // Always use the actual return length, and not our calculated expected length, if returndatacopy is supported. - // This ensures it can catch badly formatted input from external calls. - if (m_context.evmVersion().supportsReturndata()) - templ("returnSize", "returndatasize()"); - else - templ("returnSize", to_string(returnInfo.estimatedReturnSize)); - - templ("reservedReturnSize", returnInfo.dynamicReturnSize ? "0" : to_string(returnInfo.estimatedReturnSize)); + if (returnInfo.dynamicReturnSize) + solAssert(m_context.evmVersion().supportsReturndata()); + templ("returnDataSizeVar", m_context.newYulVariable()); + templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize)); + templ("supportsReturnData", m_context.evmVersion().supportsReturndata()); string const retVars = IRVariable(_functionCall).commaSeparatedList(); templ("retVars", retVars); solAssert(retVars.empty() == returnInfo.returnTypes.empty()); templ("abiDecode", m_context.abiFunctions().tupleDecoder(returnInfo.returnTypes, true)); - templ("dynamicReturnSize", returnInfo.dynamicReturnSize); + templ("isReturndataSizeDynamic", returnInfo.dynamicReturnSize); templ("noTryCall", !_functionCall.annotation().tryCall); diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json index bb3083af9..238934a3f 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json @@ -265,34 +265,39 @@ sub_0: assembly { return /* \"C\":403:411 this.f() */ tag_36: - /* \"C\":79:428 contract C... */ swap1 swap2 pop - /* \"C\":403:411 this.f() */ + 0x20 + swap1 returndatasize + dup3 + gt + tag_41 + jumpi + tag_42: /* \"C\":79:428 contract C... */ 0x1f + dup3 add not(0x1f) and - dup3 + dup4 add swap1 0xffffffffffffffff dup3 gt - dup4 + dup5 dup4 lt or - tag_41 + tag_43 jumpi pop - tag_40 swap3 /* \"C\":403:411 this.f() */ - tag_43 + tag_45 /* \"C\":392:422 stateVar + this.f() + immutVar */ tag_39 /* \"C\":79:428 contract C... */ @@ -301,34 +306,41 @@ sub_0: assembly { tag_38 /* \"C\":79:428 contract C... */ swap4 + tag_40 + swap7 0x40 mstore /* \"C\":403:411 this.f() */ - returndatasize dup2 add swap1 tag_6 jump\t// in - tag_43: + tag_45: swap3 pop swap3 jump(tag_37) /* \"C\":79:428 contract C... */ - tag_41: + tag_43: shl(0xe0, 0x4e487b71) dup2 mstore mstore(0x04, 0x41) 0x24 - swap4 + swap5 + pop + swap3 pop - swap2 pop pop revert /* \"C\":403:411 this.f() */ + tag_41: + returndatasize + swap2 + pop + jump(tag_42) tag_34: /* \"C\":79:428 contract C... */ swap3 @@ -345,10 +357,10 @@ sub_0: assembly { swap1 revert tag_32: - tag_44 + tag_46 tag_4 jump\t// in - tag_44: + tag_46: jump(tag_33) /* \"C\":117:119 41 */ tag_4: @@ -373,9 +385,9 @@ sub_0: assembly { dup5 sgt and - tag_45 + tag_47 jumpi - tag_46: + tag_48: shl(0xff, 0x01) dup3 swap1 @@ -383,25 +395,25 @@ sub_0: assembly { dup4 slt and - tag_47 + tag_49 jumpi add swap1 jump\t// out - tag_47: - tag_49 + tag_49: + tag_51 tag_4 jump\t// in - tag_49: + tag_51: add swap1 jump\t// out - tag_45: - tag_50 + tag_47: + tag_52 tag_4 jump\t// in - tag_50: - jump(tag_46) + tag_52: + jump(tag_48) /* \"C\":79:428 contract C... */ tag_6: swap1 @@ -410,12 +422,12 @@ sub_0: assembly { swap2 sub slt - tag_51 + tag_53 jumpi mload swap1 jump\t// out - tag_51: + tag_53: pop pop 0x00 @@ -732,34 +744,39 @@ sub_0: assembly { return /* \"C\":403:411 this.f() */ tag_36: - /* \"D\":91:166 contract D is C(3)... */ swap1 swap2 pop - /* \"C\":403:411 this.f() */ + 0x20 + swap1 returndatasize + dup3 + gt + tag_41 + jumpi + tag_42: /* \"D\":91:166 contract D is C(3)... */ 0x1f + dup3 add not(0x1f) and - dup3 + dup4 add swap1 0xffffffffffffffff dup3 gt - dup4 + dup5 dup4 lt or - tag_41 + tag_43 jumpi pop - tag_40 swap3 /* \"C\":403:411 this.f() */ - tag_43 + tag_45 /* \"C\":392:422 stateVar + this.f() + immutVar */ tag_39 /* \"D\":91:166 contract D is C(3)... */ @@ -768,34 +785,41 @@ sub_0: assembly { tag_38 /* \"D\":91:166 contract D is C(3)... */ swap4 + tag_40 + swap7 0x40 mstore /* \"C\":403:411 this.f() */ - returndatasize dup2 add swap1 tag_6 jump\t// in - tag_43: + tag_45: swap3 pop swap3 jump(tag_37) /* \"D\":91:166 contract D is C(3)... */ - tag_41: + tag_43: shl(0xe0, 0x4e487b71) dup2 mstore mstore(0x04, 0x41) 0x24 - swap4 + swap5 + pop + swap3 pop - swap2 pop pop revert /* \"C\":403:411 this.f() */ + tag_41: + returndatasize + swap2 + pop + jump(tag_42) tag_34: /* \"D\":91:166 contract D is C(3)... */ swap3 @@ -812,10 +836,10 @@ sub_0: assembly { swap1 revert tag_32: - tag_44 + tag_46 tag_4 jump\t// in - tag_44: + tag_46: jump(tag_33) /* \"C\":117:119 41 */ tag_4: @@ -840,9 +864,9 @@ sub_0: assembly { dup5 sgt and - tag_45 + tag_47 jumpi - tag_46: + tag_48: shl(0xff, 0x01) dup3 swap1 @@ -850,25 +874,25 @@ sub_0: assembly { dup4 slt and - tag_47 + tag_49 jumpi add swap1 jump\t// out - tag_47: - tag_49 + tag_49: + tag_51 tag_4 jump\t// in - tag_49: + tag_51: add swap1 jump\t// out - tag_45: - tag_50 + tag_47: + tag_52 tag_4 jump\t// in - tag_50: - jump(tag_46) + tag_52: + jump(tag_48) /* \"D\":91:166 contract D is C(3)... */ tag_6: swap1 @@ -877,12 +901,12 @@ sub_0: assembly { swap2 sub slt - tag_51 + tag_53 jumpi mload swap1 jump\t// out - tag_51: + tag_53: pop pop 0x00 diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 6b3c5661e..f593301bc 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -563,18 +563,24 @@ object \"C_54\" { let expr_47 if _12 { + let _13 := 32 + + if gt(_13, returndatasize()) { + _13 := returndatasize() + } + // update freeMemoryPointer according to dynamic return size - finalize_allocation(_10, returndatasize()) + finalize_allocation(_10, _13) // decode return parameters from external try-call into retVars - expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) + expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13)) } /// @src 0:399:418 \"stateVar + this.f()\" let expr_48 := checked_add_t_int256(expr_44, expr_47) /// @src 0:421:429 \"immutVar\" - let _13 := loadimmutable(\"8\") - let expr_49 := _13 + let _14 := loadimmutable(\"8\") + let expr_49 := _14 /// @src 0:399:429 \"stateVar + this.f() + immutVar\" let expr_50 := checked_add_t_int256(expr_48, expr_49) @@ -718,8 +724,10 @@ object \"C_54\" { /// @src 0:410:418 \"this.f()\" if _4 { + let _5 := 32 + if gt(_5, returndatasize()) { _5 := returndatasize() } /// @src 0:79:435 \"contract C...\" - let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 0:79:435 \"contract C...\" */ 31), not(31))) + let newFreePtr := add(_3, and(add(_5, 31), not(31))) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) { mstore(_1, shl(224, 0x4e487b71)) @@ -728,7 +736,7 @@ object \"C_54\" { } mstore(64, newFreePtr) /// @src 0:410:418 \"this.f()\" - expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) + expr := abi_decode_int256_fromMemory(_3, add(_3, _5)) } /// @src 0:399:418 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) @@ -1402,18 +1410,24 @@ object \"D_72\" { let expr_47 if _12 { + let _13 := 32 + + if gt(_13, returndatasize()) { + _13 := returndatasize() + } + // update freeMemoryPointer according to dynamic return size - finalize_allocation(_10, returndatasize()) + finalize_allocation(_10, _13) // decode return parameters from external try-call into retVars - expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) + expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13)) } /// @src 0:399:418 \"stateVar + this.f()\" let expr_48 := checked_add_t_int256(expr_44, expr_47) /// @src 0:421:429 \"immutVar\" - let _13 := loadimmutable(\"8\") - let expr_49 := _13 + let _14 := loadimmutable(\"8\") + let expr_49 := _14 /// @src 0:399:429 \"stateVar + this.f() + immutVar\" let expr_50 := checked_add_t_int256(expr_48, expr_49) @@ -1565,8 +1579,10 @@ object \"D_72\" { /// @src 0:410:418 \"this.f()\" if _4 { + let _5 := 32 + if gt(_5, returndatasize()) { _5 := returndatasize() } /// @src 1:91:166 \"contract D is C(3)...\" - let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 1:91:166 \"contract D is C(3)...\" */ 31), not(31))) + let newFreePtr := add(_3, and(add(_5, 31), not(31))) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) { mstore(_1, shl(224, 0x4e487b71)) @@ -1575,7 +1591,7 @@ object \"D_72\" { } mstore(64, newFreePtr) /// @src 0:410:418 \"this.f()\" - expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) + expr := abi_decode_int256_fromMemory(_3, add(_3, _5)) } /// @src 0:399:418 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index 64ca83041..c386cf3e8 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -60,10 +60,10 @@ contract C { // compileViaYul: also // ---- // test_bytes() -> -// gas irOptimized: 371847 +// gas irOptimized: 371919 // gas legacy: 418955 // gas legacyOptimized: 326783 // test_uint256() -> -// gas irOptimized: 522929 +// gas irOptimized: 523001 // gas legacy: 586784 // gas legacyOptimized: 451529 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index 3c1ffa6cf..cc1a182c9 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -26,6 +26,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 167672 +// gas irOptimized: 167696 // gas legacy: 169347 // gas legacyOptimized: 167269 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index 1c4e8d7a2..9deed97f1 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -61,10 +61,10 @@ contract C { // compileViaYul: also // ---- // test_bytes() -> -// gas irOptimized: 371847 +// gas irOptimized: 371919 // gas legacy: 418955 // gas legacyOptimized: 326783 // test_uint256() -> -// gas irOptimized: 522929 +// gas irOptimized: 523001 // gas legacy: 586784 // gas legacyOptimized: 451529 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol index 2aa7a251b..eec062f56 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol @@ -32,6 +32,6 @@ contract C is B { // compileViaYul: also // ---- // test() -> 77 -// gas irOptimized: 119895 +// gas irOptimized: 119919 // gas legacy: 155093 // gas legacyOptimized: 111550 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index 8d1f1a727..cf5958d45 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -21,6 +21,6 @@ contract C { // f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true -// gas irOptimized: 171838 +// gas irOptimized: 171842 // gas legacy: 141644 // gas legacyOptimized: 121532 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol index 3b0a73d00..fcf41823e 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol @@ -21,6 +21,6 @@ contract B { // compileViaYul: also // ---- // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 -// gas irOptimized: 130097 +// gas irOptimized: 130152 // gas legacy: 234943 // gas legacyOptimized: 132863 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index e9aef6d0d..73f9799d4 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -45,6 +45,6 @@ contract C { // compileViaYul: also // ---- // test() -> 5, 6, 7 -// gas irOptimized: 290567 +// gas irOptimized: 298983 // gas legacy: 452172 // gas legacyOptimized: 285017 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index 87280f6a4..ee91ce7f7 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -26,6 +26,6 @@ contract Main { // compileViaYul: also // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 113552 +// gas irOptimized: 113598 // gas legacy: 126596 // gas legacyOptimized: 113823 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 759c58d30..cc303899a 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 443921 +// gas irOptimized: 443960 // gas legacy: 590683 // gas legacyOptimized: 448326 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 7210ac269..ffe0fb8c2 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 300765 +// gas irOptimized: 300804 // gas legacy: 428917 // gas legacyOptimized: 298128 diff --git a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol index 690f555dc..5ec47a4a9 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -17,7 +17,7 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 177344 +// gas irOptimized: 173672 // gas legacy: 250376 // gas legacyOptimized: 174522 // deposit(bytes32), 18 wei: 0x1234 -> diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 2da7c2dd6..685d8a7de 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -17,7 +17,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 200295 +// gas irOptimized: 203967 // gas legacy: 245842 // gas legacyOptimized: 195676 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index 0b0633c6d..a768a2836 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -18,7 +18,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 200458 +// gas irOptimized: 204130 // gas legacy: 246202 // gas legacyOptimized: 195914 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 942faa048..030aeaa10 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -25,7 +25,7 @@ contract C { // compileViaYul: also // ---- // constructor(), 1 ether -> -// gas irOptimized: 308423 +// gas irOptimized: 315341 // gas legacy: 465314 // gas legacyOptimized: 304481 // f(uint256): 0 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index ce8d29b8b..cfbf1bcc1 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -27,7 +27,7 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 445767 +// gas irOptimized: 452673 // gas legacy: 834272 // gas legacyOptimized: 510004 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 4862f3b4c..2ebf8740d 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -18,7 +18,7 @@ contract C { // compileViaYul: also // ---- // constructor(), 20 wei -// gas irOptimized: 213663 +// gas irOptimized: 219285 // gas legacy: 294569 // gas legacyOptimized: 174699 // f(uint256): 20 -> 1370859564726510389319704988634906228201275401179 @@ -26,7 +26,7 @@ contract C { // f(uint256): 20 -> FAILURE // x() -> 1 // stack(uint256): 1023 -> FAILURE -// gas irOptimized: 304303 +// gas irOptimized: 314884 // gas legacy: 483942 // gas legacyOptimized: 298807 // x() -> 1 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index a4c3fb3dd..4321753d6 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -41,7 +41,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 274154 +// gas irOptimized: 283040 // gas legacy: 402654 // gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 5b39dda48..2f89517b7 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -40,7 +40,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 274154 +// gas irOptimized: 283040 // gas legacy: 402654 // gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/return_size_bigger_than_expected.sol b/test/libsolidity/semanticTests/functionCall/return_size_bigger_than_expected.sol new file mode 100644 index 000000000..c7a1d12bf --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/return_size_bigger_than_expected.sol @@ -0,0 +1,31 @@ +interface ShortReturn { + function f() external pure returns (bytes32); +} +contract LongReturn { + function f() external pure returns (uint[20] memory) {} +} + +contract Test { + function test() public returns (uint) { + LongReturn longReturn = new LongReturn(); + uint freeMemoryBefore; + assembly { + freeMemoryBefore := mload(0x40) + } + + ShortReturn(address(longReturn)).f(); + + uint freeMemoryAfter; + + assembly { + freeMemoryAfter := mload(0x40) + } + + return freeMemoryAfter - freeMemoryBefore; + } +} +// ==== +// compileViaYul: true +// ---- +// test() -> 0x20 +// gas legacy: 131966 diff --git a/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected.sol b/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected.sol new file mode 100644 index 000000000..5f39b877e --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected.sol @@ -0,0 +1,32 @@ +interface LongReturn { + function f() external pure returns (uint[20] memory); +} +contract ShortReturn { + function f() external pure returns (bytes32) {} +} + +contract Test { + function test() public returns (uint) { + ShortReturn shortReturn = new ShortReturn(); + uint freeMemoryBefore; + assembly { + freeMemoryBefore := mload(0x40) + } + + LongReturn(address(shortReturn)).f(); + + uint freeMemoryAfter; + + assembly { + freeMemoryAfter := mload(0x40) + } + + return freeMemoryAfter - freeMemoryBefore; + } +} +// ==== +// EVMVersion: <=homestead +// compileViaYul: true +// ---- +// test() -> 0x0500 +// gas legacy: 131966 diff --git a/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected_evm_version_after_homestead.sol b/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected_evm_version_after_homestead.sol new file mode 100644 index 000000000..225832275 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/return_size_shorter_than_expected_evm_version_after_homestead.sol @@ -0,0 +1,34 @@ +interface LongReturn { + function f() external pure returns (uint[20] memory); +} +contract ShortReturn { + function f() external pure returns (bytes32) {} +} + +contract Test { + function test() public returns (uint) { + ShortReturn shortReturn = new ShortReturn(); + uint freeMemoryBefore; + assembly { + freeMemoryBefore := mload(0x40) + } + + // This reverts. The external call succeeds but ABI decoding fails due to the returned + // `bytes32` being much shorter than the expected `uint[20]`. + LongReturn(address(shortReturn)).f(); + + uint freeMemoryAfter; + + assembly { + freeMemoryAfter := mload(0x40) + } + + return freeMemoryAfter - freeMemoryBefore; + } +} +// ==== +// EVMVersion: >homestead +// compileViaYul: true +// ---- +// test() -> FAILURE +// gas legacy: 131966 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index 840a8761b..e834663d0 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -29,7 +29,7 @@ contract C { // compileViaYul: also // ---- // f() -> 3, 7, 5 -// gas irOptimized: 127302 +// gas irOptimized: 127347 // gas legacy: 151334 // gas legacyOptimized: 125166 // x() -> 7 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 8f3584a9d..a15650992 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -25,6 +25,6 @@ contract B { // compileViaYul: also // ---- // g() -> 42 -// gas irOptimized: 111770 +// gas irOptimized: 111794 // gas legacy: 185053 // gas legacyOptimized: 114598 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index 94cd46a2d..e6f94bdcf 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -42,7 +42,7 @@ contract Main { // compileViaYul: also // ---- // constructor(), 22 wei -> -// gas irOptimized: 276469 +// gas irOptimized: 284287 // gas legacy: 402045 // gas legacyOptimized: 266772 // getFlag() -> true diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 5af1e5cdc..8d37ed809 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -18,7 +18,7 @@ contract ClientReceipt { // compileViaYul: also // ---- // constructor(), 2000 wei -> -// gas irOptimized: 184076 +// gas irOptimized: 188162 // gas legacy: 235195 // gas legacyOptimized: 176766 // balance -> 1500 diff --git a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol index 6b13ee09c..ac61fad71 100644 --- a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol +++ b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol @@ -25,6 +25,6 @@ contract Test { // ---- // library: Lib // f() -> 4, 0x11 -// gas irOptimized: 115822 +// gas irOptimized: 115874 // gas legacy: 135952 // gas legacyOptimized: 119643 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol index d85f90694..e8d22c279 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol @@ -22,6 +22,6 @@ contract Test { // ---- // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 -// gas irOptimized: 119757 +// gas irOptimized: 119561 // gas legacy: 124793 // gas legacyOptimized: 119694 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol index 9192fdfe3..86e7fa3d7 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol @@ -20,6 +20,6 @@ contract Test { // ---- // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 -// gas irOptimized: 120471 +// gas irOptimized: 120572 // gas legacy: 125245 // gas legacyOptimized: 120153 diff --git a/test/libsolidity/semanticTests/libraries/using_library_structs.sol b/test/libsolidity/semanticTests/libraries/using_library_structs.sol index 4348c377c..116887fd5 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_structs.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_structs.sol @@ -23,5 +23,5 @@ contract Test { // ---- // library: Lib // f() -> 7, 8 -// gas irOptimized: 101869 +// gas irOptimized: 101820 // gas legacy: 101504 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index af9c7e76b..4ce8b5149 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -22,6 +22,6 @@ contract A { // compileViaYul: also // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 272338 +// gas irOptimized: 272413 // gas legacy: 422501 // gas legacyOptimized: 287472 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index bd7e2fe9c..56ad74c54 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -51,7 +51,7 @@ contract C { // compileViaYul: also // ---- // test_f() -> true -// gas irOptimized: 122413 +// gas irOptimized: 122364 // gas legacy: 126168 // gas legacyOptimized: 123199 // test_g() -> true diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index 600e72e3e..1c456f1d4 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -19,7 +19,7 @@ contract D { // compileViaYul: also // ---- // constructor(), 27 wei -> -// gas irOptimized: 175261 +// gas irOptimized: 178933 // gas legacy: 222977 // gas legacyOptimized: 169779 // f() -> 27 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index ba4e7426a..30a2d9f65 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -22,6 +22,6 @@ contract C { // compileViaYul: also // ---- // g() -> 2, 6 -// gas irOptimized: 178822 +// gas irOptimized: 178812 // gas legacy: 180762 // gas legacyOptimized: 179481 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index bebf7557f..5d8bda5dd 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -22,7 +22,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 185891 +// gas irOptimized: 192113 // gas legacy: 265006 // gas legacyOptimized: 182842 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index 9edd8061a..0b2b1735b 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -21,7 +21,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> -// gas irOptimized: 187835 +// gas irOptimized: 194261 // gas legacy: 266728 // gas legacyOptimized: 184762 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol index 497dd36c8..05b7e668b 100644 --- a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol +++ b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol @@ -23,6 +23,6 @@ contract C { // compileViaYul: also // ---- // f() -> -// gas irOptimized: 113096 +// gas irOptimized: 112998 // gas legacy: 112937 // gas legacyOptimized: 112608 From cb4ffbfbb7509191483834972ee5c504f7908f08 Mon Sep 17 00:00:00 2001 From: david-k Date: Fri, 4 Mar 2022 11:02:54 +0100 Subject: [PATCH 42/45] Fix leftover use of divModWithSlacks in doc The option `divModWithSlacks` was previously changed to `divModNoSlacks`. However, this was not reflected in the documentation. --- docs/using-the-compiler.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index c6c40cacc..067c96c96 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -410,12 +410,13 @@ Input Description "source1.sol": ["contract1"], "source2.sol": ["contract2", "contract3"] }, - // Choose whether division and modulo operations should be replaced by - // multiplication with slack variables. Default is `true`. - // Using `false` here is recommended if you are using the CHC engine + // Choose how division and modulo operations should be encoded. + // When using `false` they are replaced by multiplication with slack + // variables. This is the default. + // Using `true` here is recommended if you are using the CHC engine // and not using Spacer as the Horn solver (using Eldarica, for example). // See the Formal Verification section for a more detailed explanation of this option. - "divModWithSlacks": true, + "divModNoSlacks": false, // Choose which model checker engine to use: all (default), bmc, chc, none. "engine": "chc", // Choose which types of invariants should be reported to the user: contract, reentrancy. From 66a779d2677cd322d26f7c7f304bd65092464a47 Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Fri, 4 Mar 2022 12:20:57 +0100 Subject: [PATCH 43/45] Fixing style issue in ExecutionFramework.cpp It should be `auto const&` not `const auto&` --- test/ExecutionFramework.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 600bedbf5..bb46f108d 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -266,7 +266,7 @@ h160 ExecutionFramework::logAddress(size_t _logIdx) const bytes ExecutionFramework::logData(size_t _logIdx) const { - const auto& data = m_evmcHost->recorded_logs.at(_logIdx).data; + auto const& data = m_evmcHost->recorded_logs.at(_logIdx).data; // TODO: Return a copy of log data, because this is expected from REQUIRE_LOG_DATA(), // but reference type like string_view would be preferable. return {data.begin(), data.end()}; From 17fa85a2fbe27d97d080b17d89b064ba3dc078fe Mon Sep 17 00:00:00 2001 From: Paarth Madan Date: Fri, 11 Feb 2022 22:10:36 -0500 Subject: [PATCH 44/45] Add Base64 test cases with and without inline assembly Adds two implementations of Base64 encoding as specified in RFC4648. Implementation (1) uses inline assembly, while Implementation (2) is written purely in Solidity. Assertions are added to replicate the test vectors specified in the RFC for Base64 to ensure both implementations to specification. --- .../_base64/base64_inline_asm.sol | 96 +++++++++++++++++++ .../_base64/base64_no_inline_asm.sol | 39 ++++++++ .../externalContracts/base64.sol | 61 ++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 test/libsolidity/semanticTests/externalContracts/_base64/base64_inline_asm.sol create mode 100644 test/libsolidity/semanticTests/externalContracts/_base64/base64_no_inline_asm.sol create mode 100644 test/libsolidity/semanticTests/externalContracts/base64.sol diff --git a/test/libsolidity/semanticTests/externalContracts/_base64/base64_inline_asm.sol b/test/libsolidity/semanticTests/externalContracts/_base64/base64_inline_asm.sol new file mode 100644 index 000000000..7df0c902d --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/_base64/base64_inline_asm.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev Provides a set of functions to operate with Base64 strings. + */ +library InlineAsmBase64 { + /** + * @dev Base64 Encoding/Decoding Table + */ + string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + /** + * @dev Converts a `bytes` to its Bytes64 `string` representation. + */ + function encode(bytes memory data) internal pure returns (string memory) { + /** + * Inspired by OpenZepplin Base64 implementation + * https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2884/commits/157c32b65a15cb0b58257543643cafa1cebf883a + */ + if (data.length == 0) return ""; + + // Loads the table into memory + string memory table = _TABLE; + + // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter + // and split into 4 numbers of 6 bits. + // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up + // - `data.length + 2` -> Round up + // - `/ 3` -> Number of 3-bytes chunks + // - `4 *` -> 4 characters for each chunk + uint256 encodedLen = 4 * ((data.length + 2) / 3); + + // Add some extra buffer at the end required for the writing + string memory result = new string(encodedLen); + + assembly { + // Store the actual result length in memory + mstore(result, encodedLen) + + // Prepare the lookup table + let tablePtr := add(table, 1) + + // Prepare input pointer + let dataPtr := data + let endPtr := add(dataPtr, mload(data)) + + // Prepare result pointer, jump over length + let resultPtr := add(result, 32) + + // Run over the input, 3 bytes at a time + for { + + } lt(dataPtr, endPtr) { + + } { + // Advance 3 bytes + dataPtr := add(dataPtr, 3) + let input := mload(dataPtr) + + // To write each character, shift the 3 bytes (24 bits) chunk 4 + // times in blocks of 6 bits for each character (18, 12, 6, 0) + // and apply logical AND with 0x3F to extract the 6-bit group. + // Add the 6-bit group with the table ptr to index into the + // table and acquire the character to write. Finally, write + // the character to the result pointer. + + mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + + mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) + resultPtr := add(resultPtr, 1) // Advance + } + + // When data `bytes` is not exactly 3 bytes long + // it is padded with `=` characters at the end + switch mod(mload(data), 3) + case 1 { + mstore8(sub(resultPtr, 1), 0x3d) + mstore8(sub(resultPtr, 2), 0x3d) + } + case 2 { + mstore8(sub(resultPtr, 1), 0x3d) + } + } + + return result; + } +} diff --git a/test/libsolidity/semanticTests/externalContracts/_base64/base64_no_inline_asm.sol b/test/libsolidity/semanticTests/externalContracts/_base64/base64_no_inline_asm.sol new file mode 100644 index 000000000..f54d2f925 --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/_base64/base64_no_inline_asm.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev Provides a set of functions to operate with Base64 strings. + */ +library NoAsmBase64 { + bytes private constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + function encode(bytes memory data) internal pure returns (string memory) { + if (data.length == 0) return ""; + + bytes memory table = TABLE; + bytes memory result = new bytes(4 * ((data.length + 2) / 3)); + uint256 resultPtr = 0; + + for (uint256 dataPtr = 0; dataPtr < data.length; dataPtr += 3) { + uint24 chunk = ( (uint24(uint8(data[dataPtr + 0])) << 16)) + + (dataPtr + 1 < data.length ? (uint24(uint8(data[dataPtr + 1])) << 8) : 0) + + (dataPtr + 2 < data.length ? (uint24(uint8(data[dataPtr + 2])) ) : 0); + + result[resultPtr++] = table[uint8(chunk >> 18) & 0x3f]; + result[resultPtr++] = table[uint8(chunk >> 12) & 0x3f]; + result[resultPtr++] = table[uint8(chunk >> 6) & 0x3f]; + result[resultPtr++] = table[uint8(chunk ) & 0x3f]; + } + + if (data.length % 3 == 1) { + result[--resultPtr] = 0x3d; + result[--resultPtr] = 0x3d; + } + else if (data.length % 3 == 2) { + result[--resultPtr] = 0x3d; + } + + return (string(result)); + } +} diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol new file mode 100644 index 000000000..fd17c5d78 --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -0,0 +1,61 @@ +==== ExternalSource: _base64/base64_inline_asm.sol ==== +==== ExternalSource: _base64/base64_no_inline_asm.sol ==== +==== Source: base64.sol ==== + +import "_base64/base64_inline_asm.sol"; +import "_base64/base64_no_inline_asm.sol"; + +contract test { + function encode_inline_asm(bytes memory data) external pure returns (string memory) { + return InlineAsmBase64.encode(data); + } + + function encode_no_asm(bytes memory data) external pure returns (string memory) { + return NoAsmBase64.encode(data); + } + + function encode_inline_asm_large() external { + for (uint i = 0; i < 1000; i++) { + InlineAsmBase64.encode("foo"); + } + } + + function encode_no_asm_large() external { + for (uint i = 0; i < 1000; i++) { + NoAsmBase64.encode("foo"); + } + } +} +// Test cases derived from Base64 specification: RFC4648 +// https://datatracker.ietf.org/doc/html/rfc4648#section-10 +// +// ==== +// EVMVersion: >=constantinople +// compileViaYul: also +// ---- +// constructor() +// gas irOptimized: 450044 +// gas legacy: 766936 +// gas legacyOptimized: 543094 +// encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 +// encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" +// encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" +// encode_inline_asm(bytes): 0x20, 3, "foo" -> 0x20, 4, "Zm9v" +// encode_inline_asm(bytes): 0x20, 4, "foob" -> 0x20, 8, "Zm9vYg==" +// encode_inline_asm(bytes): 0x20, 5, "fooba" -> 0x20, 8, "Zm9vYmE=" +// encode_inline_asm(bytes): 0x20, 6, "foobar" -> 0x20, 8, "Zm9vYmFy" +// encode_no_asm(bytes): 0x20, 0 -> 0x20, 0 +// encode_no_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" +// encode_no_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" +// encode_no_asm(bytes): 0x20, 3, "foo" -> 0x20, 4, "Zm9v" +// encode_no_asm(bytes): 0x20, 4, "foob" -> 0x20, 8, "Zm9vYg==" +// encode_no_asm(bytes): 0x20, 5, "fooba" -> 0x20, 8, "Zm9vYmE=" +// encode_no_asm(bytes): 0x20, 6, "foobar" -> 0x20, 8, "Zm9vYmFy" +// encode_inline_asm_large() +// gas irOptimized: 1385047 +// gas legacy: 1658033 +// gas legacyOptimized: 1210033 +// encode_no_asm_large() +// gas irOptimized: 3335101 +// gas legacy: 4801077 +// gas legacyOptimized: 2929077 From 06820e1b1eee5b20bf53d9e8d5c9dbbd241b8b4c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 7 Mar 2022 12:14:08 +0100 Subject: [PATCH 45/45] Remove unused entry point to evmasm Assembly. --- libevmasm/Assembly.cpp | 20 -------------------- libevmasm/Assembly.h | 7 ------- 2 files changed, 27 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 12c7be230..55d23e283 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -397,26 +397,6 @@ AssemblyItem Assembly::newImmutableAssignment(string const& _identifier) return AssemblyItem{AssignImmutable, h}; } -Assembly& Assembly::optimise(bool _enable, EVMVersion _evmVersion, bool _isCreation, size_t _runs) -{ - OptimiserSettings settings; - settings.isCreation = _isCreation; - settings.runInliner = true; - settings.runJumpdestRemover = true; - settings.runPeephole = true; - if (_enable) - { - settings.runDeduplicate = true; - settings.runCSE = true; - settings.runConstantOptimiser = true; - } - settings.evmVersion = _evmVersion; - settings.expectedExecutionsPerDeployment = _runs; - optimise(settings); - return *this; -} - - Assembly& Assembly::optimise(OptimiserSettings const& _settings) { optimiseInternal(_settings, {}); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index f768ffe31..97807e223 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -134,13 +134,6 @@ public: /// is optimised according to the settings in @a _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. - /// @a _runs specifes an estimate on how often each opcode in this assembly will be executed, - /// i.e. use a small value to optimise for size and a large value to optimise for runtime. - /// If @a _enable is not set, will perform some simple peephole optimizations. - Assembly& optimise(bool _enable, langutil::EVMVersion _evmVersion, bool _isCreation, size_t _runs); - /// Create a text representation of the assembly. std::string assemblyString( langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),